home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume91 / shells / cshel510 / part02 < prev    next >
Encoding:
Internet Message Format  |  1991-04-16  |  67.0 KB

  1. Path: news.larc.nasa.gov!amiga-request
  2. From: amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator)
  3. Subject: v91i089: CShell 5.10 - alternative command interface, Part02/06
  4. Reply-To: umueller@iiic.ethz.ch
  5. Newsgroups: comp.sources.amiga
  6. Message-ID: <comp.sources.amiga:v91i089@ab20.larc.nasa.gov>
  7. References: <comp.sources.amiga:v91i088@ab20.larc.nasa.gov>
  8. Date: 16 Apr 91 19:34:37 GMT
  9. Approved: tadguy@uunet.UU.NET (Tad Guy)
  10. X-Mail-Submissions-To: amiga@uunet.uu.net
  11. X-Post-Discussions-To: comp.sys.amiga.misc
  12.  
  13. Submitted-by: umueller@iiic.ethz.ch
  14. Posting-number: Volume 91, Issue 089
  15. Archive-name: shells/cshell-5.10/part02
  16.  
  17. #!/bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of archive 2 (of 6)."
  24. # Contents:  changes.doc csh.doc.ad rawcon.c sub.c
  25. # Wrapped by tadguy@ab20 on Tue Apr 16 15:34:34 1991
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'changes.doc' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'changes.doc'\"
  29. else
  30. echo shar: Extracting \"'changes.doc'\" \(11556 characters\)
  31. sed "s/^X//" >'changes.doc' <<'END_OF_FILE'
  32. XNew features to 5.10:
  33. X- totally rewritten parser, therefore:
  34. X-  local variables, in aliases as well as in batch files
  35. X-  blocks can be formed, redirected, aborted: {e yo;e ho}
  36. X-  $(foo) will insert output of program foo at that point, similar with `foo`
  37. X-  wildcard expansion also done in first arg, e.g. '*' is a legal command line
  38. X-  command lines like '$mydir/$mycommand ram:' now works
  39. X-  aliases/foreach/forline/fornum/source can be redirected as a whole
  40. X-  direct recursion in aliases prevented, 'alias ls "ls -s"' works
  41. X-  additional speedup; twice as fast as 4.xx, four times as fast as c:Execute
  42. X- '.bra' and '.ket' introduced as dummy commands for script compatibility
  43. X- 'assign' now yields a list of all assings including late/nonbinding, paths
  44. X- 'assign -p' does path assigns (like 'c:Assign ... ADD)
  45. X- 'cat' CR terminated non-CR-termintad files again if not redirected
  46. X- 'class' can pattern-match now, e.g. 'class sound name="mod.*"'
  47. X- 'copy' has a larger buffer and checks for ^C more often
  48. X- 'copy -m' moves files (but not directories yet)
  49. X- 'dir -p' prints full paths and suppresses titles
  50. X- 'dir' can separate direcories at the top or bottom
  51. X- 'dir -z formatstring' is a very powerful formatting feature
  52. X- 'error' generates a desired return code
  53. X- 'forline i STDIN' reads args from stdin
  54. X- 'input' removes leading, trailing and multiple blanks
  55. X- 'local' and 'unlocal' for generating and deleting local variables
  56. X- 'man' can handle multiple .doc files, so you can document your own aliases
  57. X- 'mem' uses , instead of ' and is right adjusted
  58. X- 'source' can handle multiple line blocks of arbitrary length
  59. X- 'qsort' can now sort in reverse order
  60. X- 'rback'/'run' now set the variable '$_newproc' to the # of the new process
  61. X- $_abbrev can be used to disable abbreviation if internal commands
  62. X- $_ioerr contains the secondary return code after an error
  63. X- $_path now contains S: and CSH: in order to run scripts
  64. X- $_pipe now holds the directory for the temporary pipe files
  65. X- $_verbose need to be set to special values, now can trace alias calls
  66. X- @console tells whether stdin or stdout are interactive
  67. X- @ioerr converts a secondary error number to a string (like 'Why')
  68. X- @mounted indicates whether a device has been mounted yet or not
  69. X- @sortnum sorts its arguments numerically
  70. X- @volume now suppresses ugly system requesters
  71. X- shift-arrow-up and shift-arrow-down now behave like under AmigaDOS
  72. X- there is now an editing function that duplicates the last word
  73. X- csh has a startup option to enable '*' as an alias for '#?' in AmigaDOS
  74. X- a directory CSH: is proposed for scripts and the doc
  75. X- concatted lines in source files can be as long as you want
  76. X- . now stands for current directory, .. for parent
  77. X- soft and hard links to directories are ignored on wild card expansion
  78. X
  79. XBug fixes of 5.10 (in order of severity):                  bug present since
  80. X- AmigaDOS residents should work fine now. V37 kickstart required       5.00
  81. X- 'Wait 5&' as an alias for 'rback Wait 5' now works                    5.00
  82. X- 'rm -r ram:' and 'search -r "" hello' finally do their job            4.00
  83. X- 'c:execute' works. check the restrictions chapter                     3.00
  84. X- '!!' was broken in the first parser rewrite, fixed now.               5.00
  85. X- 'return' occasionally didn't skip the whole source file               5.00
  86. X- '~' now can correctly be used in path names: ~/*.c                    5.00
  87. X- 'Repeat' from menu caused a loop (correct behaviour!)                 5.00
  88. X- 'forline' no longer crashes if the from-file does not exist           4.00
  89. X- 'set x 1 2;echo hello$x' finally yields 'hello1 2'.                   1.00
  90. X- 'goto' also works if there are '\' in the source file                 4.00
  91. X- command line editing on VT100's was broken. fixed.                    5.00
  92. X- low mem situations now cause a graceful exit instead of a crash       1.00
  93. X- actions on files with embedded blanks are performed correcty          5.00
  94. X- 'man' no longer opens garbage files (SnoopDos is hard to cheat)       5.00
  95. X- 'dir -o' now works (ls -o always did)                                 5.00
  96. X- 'dir df0:' with no disk in drive yields correct error message         5.00
  97. X- 'dir' no longer adds line feeds to invalid date stamps                5.00
  98. X- 'set _prompt "% "' is now allowed (not only 'set _prompt "%% "')      5.00
  99. X- 'search -l' no longer does unnecessary line feeds                     5.00
  100. X- '@pickopts' stops picking options at the first non-option             5.00
  101. X- system requesters are no longer unintentionally disabled              5.00
  102. X
  103. XIncompatibilities in 5.10
  104. X- a stand-alone '.' must be quoted now. check your strhead's and strtail's!
  105. X- the quick-cd file and the manual (now named csh.doc) should reside in csh:
  106. X- some builtin aliases and preset function keys have been moved to compat.sh
  107. X- the functions of shift-arrow-up & down are mapped to esc-arrow-up & down
  108. X- the path is now searched before auto CD is attempted (mimicking AmigaDOS)
  109. X- the characters { } @ ( ) should be quoted if you just want to echo them
  110. X- a redirection error now causes a return code of 20 instead of 1
  111. X- _verbose now holds numeric values, 'set _verbose yes' won't work anymore
  112. X- @volume no longer appends a trailing colon to the volume name
  113. X- an empty string is now passed to external commands as ""
  114. X- future: a leading '/' and '~' might change meaning towards UNIX
  115. X
  116. XNew features to 5.00
  117. X- read the doc! almost everything's new.
  118. X
  119. XBug fixes to 5.00: 
  120. X- recursive wild card expansion does not crash the Amiga 3000 anymore
  121. X- recursive wild card expansion does not lose memory anymore
  122. X- now works on AUX:
  123. X- trying to start a non-object-file now properly prints 'Command Not Found'
  124. X- automatic sourcing now also works if you already add .sh to the file name
  125. X- files longer than 999999 bytes no longer misalign 'dir'
  126. X- exec does not discard the rest of the command line ('exec echo hi;echo ho')
  127. X- all memory trashing fixed. Thanks to C= for their great debugging tools!
  128. X- source doesn't forget last character if batchfile was not CR terminated
  129. X- run & rback also search AmigaDOS path now
  130. X- division by zero does not crash rpn anymore
  131. X- temporary pipe files are now written to t: instead of ram:
  132. X- shift-tab does not cause a lockup anymore
  133. X- running the shell via aux: no longer crashes the machine
  134. X- 'history partial' now numbers the lines correctly
  135. X- strleft, strright and strmid no longer crash on strings > 256 bytes
  136. X- source with no arguments now prints correct error message
  137. X- 'input' now cuts down lines longer than 256 bytes instead of crashing
  138. X- cursor-up no more deletes lines if there's an invalid entry in the history
  139. X- if history fails, no empty history entry is generated
  140. X- 'echo "---"' and even 'echo ---' work, but 'echo "-a"' still doesn't
  141. X- international character sets can be used
  142. X- 'copy -u' won't copy a file with identical date stamp but in uppercase
  143. X- 'copy -u' will no longer access low memory
  144. X- 'echo "echo mem | shell" | shell' now works, not only every second time
  145. X- starting from workbench now prevented
  146. X- editing lines longer than 256 bytes is now correctly prevented
  147. X- word-right cursor movement works correclty with multiple blanks
  148. X- 'if'-stack will be adjusted when a batch file is exited
  149. X- relabel occasionally crashed in Syquest drives. should be okay now
  150. X
  151. XKnown bugs in 5.00:
  152. X- under 2.0, doing a 'cat' with no args and pressing return will cause a 
  153. X  character to appear at the right border of the window. seems to be a
  154. X  kickstart bug, as it does not happen under older kickstarts.
  155. X- AmigaDOS 2.0 CLI commands cannot be made resident. They read their command
  156. X  line from stdin. This is definitely a kickstart bug.
  157. X- guaranteed to crash in extreme low mem situations
  158. X- command line editing doesn't quite work on a (physical) vt100. OK on VT200
  159. X- under kick 2.00, fast repetition of ^W crashed. OK under 2.02
  160. X- 'set x a b;echo hello$x' still outputs only 'a b'
  161. X
  162. XIncompatibilities in 5.00:
  163. X- 'copy -f' now means 'freshen'. Old meaning of -f is now -p (protection)
  164. X- '~' at the beginning of a file name must now be quoted
  165. X- '@' is the beginning of an argument should be quoted
  166. X- 'cat' no longer adds a CR to a non-CR-terminated file
  167. X- '0' is now 'false'. Example: 'if 0;e hi;else;e ho;endif --> ho
  168. X- variables with comparision operators inside now cause problems in 'if'
  169. X- a single '?' will not pattern match, but be passed as a string
  170. X
  171. X
  172. X
  173. XNew to 4.02A:
  174. X- Fixed bug that caused loss of memory on exit.
  175. X- cp now copies protection bits; use -f switch if you want to avoid this.
  176. X- Added  commands: man (and alias manlist), uniq, head, tail, tee.
  177. X- This doc has been reformatted to work with man.
  178. X
  179. XNew to 4.01A:
  180. X- This version features mostly bug fixes and corrections:
  181. X * Window title is restored after quitting.
  182. X * rxrec now answers to the 'bye' message.
  183. X * rpn can now be redirected and piped; however, this causes
  184. X    some problem (see rpn for info).
  185. X * resident list now works with ARP 1.3. To recompile source, you must
  186. X    modify include file "libraries/arpbase.h".
  187. X    Change definition of rpn_Usage in struct ResidentProgramNode from LONG
  188. X    to WORD.
  189. X * pri no more assumes 20 CLI maximum.
  190. X * you can now split long lines in source files even into more than 2 lines.
  191. X- Added much info in this doc about source files (chapter XI)
  192. X- Added copyright notice (see under restrictions).
  193. X
  194. XNew to 4.00A:
  195. X- This version is called 4.00A because it is not 100% compatible with
  196. X  previous versions. We choose to accept this in order to better support
  197. X  the new ARP.library 1.3.
  198. X- External commands are searched in a different order than before; Shell
  199. X  path is now searched AFTER current directory, AmigaDOS path and C:.
  200. X- ARP pattern matching has been implemented (in part for line arg expanding,
  201. X  fully for search -w).
  202. X- Internal changes for various optimizations.
  203. X- Search command has been improved in several ways.
  204. X- New commands: basename, tackon.
  205. X- New options: if -v, resident -d, fornum -v -s, dir -n.
  206. X- Fixed bugs with dir (some dirs remained locked), foreach -v, htype
  207. X  (blanks were treated as binary), info (for devices > 32M).
  208. X- rback command now works ok (run, however, doesn't).
  209. X- Oh, I forgot: it also has an AREXX port... And you don't even have to get
  210. X  AREXX to use it. See new commands rxsend, rxrec
  211. X
  212. XNew to 3.03A:
  213. X- New filter commands fltlower, fltupper.
  214. X- Added configuration file feature: now if you have a file named S:.login,
  215. X  it will be sourced for every Shell you start.
  216. X- New option dir -c.
  217. X- New editing feature: shift-left(right) arrow move cursor to previous(next)
  218. X  word.
  219. X- Bugs fixed: alias command wasn't listed in help; typing a number as a
  220. X  command was interpreted like 'alias'.
  221. X
  222. XNew to 3.02A:
  223. X- New commands: fornum, forline, strleft, strright, strmid, strlen, exec.
  224. X- Improved commands: foreach, pri.
  225. X- New system variable _clinumber.
  226. X- You can now split long lines in source files (see source for details).
  227. X- window -q now lists also position of screens/windows, not only dimension.
  228. X- Since strings are handled directly from Shell with new commands,
  229. X  rpn is now used only for calculations; string commands are gone.
  230. X  However, now RPN is really usable.
  231. X- Changed rawgets() to fix some problems with function keys, multi-line
  232. X  editing and window resizing; also, fixed bug with ^E.
  233. X- cat now warns you if it can't find any file matching your pattern.
  234. X- Now uses DOS packets to get ptr to CLI window; this fixes a bug that
  235. X  caused problems if Shell was run on unactive windows.
  236. X- Fixed minor bugs (htype printed some more ASCII bytes, some commands
  237. X  returned random values, history didn't print CR's).
  238. END_OF_FILE
  239. if test 11556 -ne `wc -c <'changes.doc'`; then
  240.     echo shar: \"'changes.doc'\" unpacked with wrong size!
  241. fi
  242. # end of 'changes.doc'
  243. fi
  244. if test -f 'csh.doc.ad' -a "${1}" != "-c" ; then 
  245.   echo shar: Will not clobber existing file \"'csh.doc.ad'\"
  246. else
  247. echo shar: Extracting \"'csh.doc.ad'\" \(11563 characters\)
  248. sed "s/^X//" >'csh.doc.ad' <<'END_OF_FILE'
  249. X    If  no  _except variable exists, any command which fails causes the
  250. X    rest of the line to abort as if an ABORTLINE had been executed.  If
  251. X    the _except variable exists, it is of the form:
  252. X
  253. X    "nnn;commands..."
  254. X
  255. X    where  nnn  is  some  value  representing  the  minimum return code
  256. X    required  to  cause  an  error.   Whenever a command returns a code
  257. X    which  is  larger  or  equal  to  nnn,  the commands in _except are
  258. X    executed  before  anything.   WHEN _except EXISTS, THE COMMAND LINE
  259. X    DOES  NOT  ABORT AUTOMATICALLY.  Thus, if you want the current line
  260. X    being executed to be aborted, the last command in _except should be
  261. X    an "abortline".
  262. X
  263. X    Exception  handling  is  disabled  while  in the exception handling
  264. X    routine (thus you can't get into any infinite loops this way).
  265. X
  266. X    Thus if _except = ";", return codes are completely ignored.
  267. X
  268. X    Example:
  269. X
  270. X    set _except "20;abortline"
  271. X
  272. X
  273. XXII. EXAMPLE SOURCE FILES
  274. X-------------------------
  275. X
  276. XIf from a CLI or the startup-script you say 'SHELL filename', that file is
  277. Xsourced first.
  278. X
  279. X### compat.sh ###
  280. X
  281. X# this makes sure that your old abbreviations don't call new commands
  282. X
  283. Xalias as  aset
  284. Xalias cl  close
  285. Xalias g   goto
  286. Xalias h   help
  287. Xalias he  help
  288. Xalias m   md
  289. Xalias q   quit
  290. Xalias re  rename
  291. Xalias w   window
  292. X
  293. Xalias kr  "rm -r ram:* >NIL:
  294. X
  295. X### End of compat.sh ###
  296. X
  297. X
  298. XMoreover, if you have a file called S:.login, it will be sourced for every
  299. XShell you run. This is useful for aliases and setting that you want in ALL
  300. XShells.
  301. X
  302. X
  303. X### Example S:.login ###
  304. X
  305. XHere is an example .login file:
  306. X
  307. Xset F5 "cdir WORK:"^M
  308. Xset f9 "ed s:login.sh"^M
  309. Xset F9 "ed df0:s/startup-sequence"^M
  310. X
  311. Xalias toram  "%q foreach i ( $q ) \"cp -r $i: ram:$i >NIL:;assign $i: ram:$i
  312. Xalias ramop  "md RAM:op; assign OP: ram:op
  313. Xalias noop   "assign OP: ; rm -r ram:op
  314. Xalias newop  "rm -r OP:*
  315. Xalias dc     "dfc df0: to df1:
  316. Xalias go     "%q assign WORK: Boot:$q; cd WORK:; source startme.sh
  317. Xalias get    "%q cp $q RAM: >NIL:
  318. Xalias filter "%a%b%c exec $b \\<$a \\>$c
  319. X    # reads $a, filters it with $b and writes result to $c
  320. X
  321. Xalias rm     "%q \\rm @confirm( Remove $q )
  322. X
  323. X#alias rm     "%a set f @pickargs( $a );set opts @pickargs( $a );\
  324. X# e -n OK to delete @words( @files( $f ) ) file(s) and @words( @dirs( $f ) )\
  325. X# directories\"? \";input b;if $b = y;\\rm $opts $f;endif 
  326. X#        # for the anxious among us: confirmed rm
  327. X
  328. Xset _prompt   "%c%p> "
  329. X    # this puts the path highlighted in the prompt
  330. X
  331. X# this one puts cli number, free mem, date and time in title bar
  332. Xset _titlebar "Shell %n    Mem %m     Date %d    Time %t
  333. X
  334. X# This file will be sourced for every Shell you start
  335. X
  336. X### End of example .login ###
  337. X
  338. X****************************************************************************
  339. X
  340. XIf you are a CLI user, your startup-sequence may be as simple as:
  341. X
  342. X    C:csh S:startup.sh
  343. X
  344. XHere's a startup code:
  345. X
  346. X### Example S:startup.sh ###
  347. X
  348. Xwind -l    # if you are on a PAL machine, or use overscan
  349. X    # note that commands may be abbreviated (wind=window)
  350. X
  351. Xassign LC: Stuff:c  INCLUDE: Stuff:include   LIB: Boot:lib   QUAD: RAM:
  352. X
  353. Xrback C:FaccII; sleep 1
  354. X    # after spawning a process, it is always better to allow it
  355. X    # to load the command, to avoid excessive drive head movement
  356. X
  357. Xresident -d blink lc1 lc2 >NIL:    #defer loading
  358. X
  359. XC:PopCli 300 C:Newcli         #using full pathname loads faster
  360. XC:FF -1 Siesta.font >NIL:
  361. XC:Patch_1 >NIL:
  362. Xstack 8000            # lc1 and lc2 need this
  363. X
  364. Xsource S:setdate.sh        # this is listed next 
  365. X
  366. X### End of example startup.sh ###
  367. X
  368. X****************************************************************************
  369. X
  370. XThe following is an example source file to set date and time; it may be
  371. Xused at startup if you don't have an internal clock.
  372. X
  373. X### setdate.sh ###
  374. X
  375. Xopen CON:200/100/440/80/SetDate write 1
  376. Xecho >.1 -n "Current date is "
  377. Xdate >.1
  378. Xecho >.1 -n "Please enter date: "
  379. Xinput <.1 d
  380. Xclose 1
  381. Xstrlen len $d
  382. Xif $len > 1 ; date $d ; endif
  383. Xecho -n "New date: " ; date
  384. X
  385. X### End of setdate.sh ###
  386. X
  387. X***************************************************************************
  388. X
  389. XNext comes a makefile that needs no Make program: may be executed from
  390. XShell directely!!!
  391. X
  392. X### make.sh ###
  393. X
  394. Xif -t Shell.syms Shell.h; cc +HShell.syms Shell.h; rm shell.o; endif
  395. Xif -t RAM:Shell.syms Shell.syms; cp -d Shell.syms RAM:; endif
  396. X
  397. Xforeach i ( main comm1 comm2 comm3 execom globals rawconsole run set \
  398. X sub ) "if -t $i.o $i.c; echo Compile $i...;cc +IRAM:shell.syms $i.c; endif"
  399. X
  400. X# we used line continuation for better visibility. this is not necessary,
  401. X# you can type it all in one line. no more limit of 256 bytes per line
  402. X
  403. Xif -t Shell run.o main.o comm1.o comm2.o comm3.o execom.o \
  404. Xset.o sub.o globals.o rawconsole.o
  405. X    ln  +q -m -o Shell run.o main.o comm1.o comm2.o comm3.o\
  406. X    execom.o set.o sub.o globals.o rawconsole.o -la -lc
  407. Xendif
  408. X
  409. X### End of make.sh ###
  410. X
  411. X
  412. XXIII.  Default Values
  413. X--------------------
  414. X
  415. XTo make things easier, some aliases are predefined whenever you start a
  416. Xnew Shell. These are:
  417. X
  418. X    CLS
  419. X    Simply clear the screen.
  420. X
  421. X    CDIR
  422. X    Use "cdir directory" to clear the screen, set CD to directory,
  423. X    and list it.
  424. X
  425. X    EXIT
  426. X    Leave Shell and exit CLI.
  427. X
  428. X    FG
  429. X    Runs current shell in foreground, this means priority 1.
  430. X
  431. X    KR
  432. X    Used to delete everything on RAM:. This one is gone, if you still
  433. X    want it, you'll have to put it in your s:.login
  434. X
  435. X    LP
  436. X    List to printer one or more files.
  437. X
  438. X    MANLIST
  439. X    Display  a list of possible arguments to man.  You can pipe this to
  440. X    qsort to get a sorted output.
  441. X
  442. X    NICE
  443. X    Sets this shell to priority -1.
  444. X
  445. XMoreover, many variables have default values, and many function keys are
  446. Xpredefined. You can use set command to determine all of these.
  447. X
  448. XXIV.  Object oriented features
  449. X------------------------------
  450. X
  451. X    CLASSES OF FILES
  452. X
  453. X    You can define a class of files using several 'class' commands.
  454. X    Here a simple example:
  455. X
  456. X      class picture  suff=.pic suff=.iff suff=.ilbm 
  457. X      class anim     suff=.anim
  458. X
  459. X    From now on, everything with the suffix .pic, .iff or .ilbm will
  460. X    be identified as a picture. Please note that there may be no blanks
  461. X    between the names and the '=', and that blanks inside the names
  462. X    must be put in quotes. So these are the ways to identify a file:
  463. X
  464. X      suff=.doc        True if the suffix of the file is .doc
  465. X      name=readme      True if the file is "readme"
  466. X      name="mod.*"     True if the name starts with 'mod.'
  467. X      offs=14,DC..C4FD True if the bytes starting at $14 are $DC,
  468. X                       anything, $C4, $FD  (all numbers hexadecimal!). 
  469. X                       Each pair of dots means one byte ignored.
  470. X      chars            True if 90% of the bytes in the file are 32..127
  471. X                       or 9..13
  472. X      default          Always true, used to define the default type
  473. X
  474. X    Note that only the first character is examined, so 's' = 'suff'.
  475. X    One class can be identified by more than one 'class' statement.
  476. X    They are looked at in the same sequence they were entered. So to
  477. X    make sure that an zoo archive misnamed as .lzh is identified
  478. X    correctly, use the following 'class' statements:
  479. X
  480. X      class zoo offs=14,DCA7C4FD
  481. X      class lzh offs=2,2D6C68..2D
  482. X      class zoo suff=.zoo
  483. X      class lzh suff=.lzh
  484. X
  485. X    Moreover, there is a builtin class 'dir', which means directory.
  486. X    Now we know many file types. But what to do with them? This is
  487. X    where we define 'actions'.
  488. X
  489. X    ACTIONS ON CLASSES
  490. X
  491. X    There may be one or more 'class' commands that define what actions
  492. X    need to be taken in various cases for that specific class:
  493. X
  494. X      class zoo actions view="zoo -list" extr="zoo -extract"
  495. X      class lzh actions view="lz l"      extr="lz e"
  496. X
  497. X    Whenever somebody tries to 'view' a test.zoo, the command
  498. X    'zoo -list test.zoo' will be issued, but if he tries to
  499. X    view test.lzh, then 'lz l test.lzh' will be executed. Note
  500. X    that any command supplied here goes through the normal csh
  501. X    parser, so AmigaDOS and csh paths will be searched. Aliases
  502. X    with arguments are allowed here, too, so whatever the user
  503. X    typed will be stored in the variable after the '%'.
  504. X
  505. X    How do I tell a file that I want to 'view' it? There comes the
  506. X    second command used for object oriented features:
  507. X
  508. X      action view test.zoo
  509. X
  510. X    will first identify the type of that file and then apply, if
  511. X    possible, the 'view' action to it. Of course, this works best
  512. X    inside an alias:  alias v "action view" will define a v-command
  513. X    that views all types of files known to cshell. Similarly, you
  514. X    can define   alias xtr "action extr" and use this command to
  515. X    extract files from any type of archive.
  516. X    There is one action that will be sent to every file that you
  517. X    try to start but is not executable. This action is 'exec'. 
  518. X    Assume you have defined the class 'picture', then after
  519. X
  520. X      class picture actions view=Mostra exec=Mostra
  521. X
  522. X    you can display a picture using Mostra by just typing its name.
  523. X    More builtin actions like 'rm' and 'dir' may be implemented,
  524. X    so don't use command names for action names.
  525. X
  526. X    The batch file class.sh defines a few useful classes.
  527. X
  528. X
  529. X
  530. XXV.     Keymaps
  531. X---------------
  532. X
  533. X    You define a keymap as a collection of key/function pairs. Both
  534. X    are given as numbers. There can be several keymaps which activate
  535. X    each other, but at first we only edit keymap 0, which is active
  536. X    at the beginning. All keys you define will eventually overwrite
  537. X    the old definitions in an existing keymap. Everithing marked with
  538. X    a (*) is not yet implemented.
  539. X
  540. X    KEYCODES
  541. X
  542. X    1..255    The corresponding ASCII character
  543. X    256      Up Arrow
  544. X    257      Down Arrow
  545. X    258      Right Arrow
  546. X    259      Left Arrow
  547. X    260      Help
  548. X    261..270  F1..F10  (unshifted)
  549. X
  550. X
  551. X    Modifiers (add them to the key code)
  552. X
  553. X    512       SHIFT (only necessary for arrows and fkeys)
  554. X    1024      ESC   (was pressed & released before this key)
  555. X
  556. X    EDITFUNCTIONS
  557. X
  558. X    - Movement      Move cursor...
  559. X     0  CursLeft    1 left
  560. X     1  CursRight   1 right
  561. X     2  WordLeft    1 word left
  562. X     3  WordRight   1 word right
  563. X     4  BegOfLine   to beginning of line
  564. X     5  EndOfLine   to end of line
  565. X
  566. X    - Deleting      Delete...
  567. X    10  Backspace   char left from cursor
  568. X    11  Delete      char right from cursor
  569. X    12  BkspcWord   word left from cursor
  570. X    13  DelWord     word right from cursor
  571. X    14  DeleteToSOL to start of line
  572. X    15  DeleteToEOL to end of line
  573. X    16  DeleteLine  whole line
  574. X
  575. X    - History insert
  576. X    20  Back        Move one line back in history
  577. X    21  Forward     Move one line forward in history
  578. X    22  Beg         Move to first line in history
  579. X    23  End         Move to last line in history
  580. X    24  Complete    History retrieve like '!'
  581. X    25  Exec        Execute history line & bring up next
  582. X    26  Tail        Insert previous line except first word
  583. X    27  Bottom      Go below last history command
  584. X    28  DupWord     Duplicates the last word on this line
  585. X
  586. X    - Completion
  587. X    30  Normal      Insert first matching file (or cycle)
  588. X    31  Partial     Insert substring of all matching files
  589. X    32  All         Insert all matching files
  590. X    33  Directory   Find dir in quick cd list
  591. X    34  LastCD      Insert last current directory
  592. X
  593. X    - Special
  594. X    40  Insert      Toggle Insert/Overwrite
  595. X    41  Quit        Silently perform 'quit'
  596. X    42  Help        Silently perform 'help'
  597. X    43  Refresh     Redraw current line
  598. X    44  Execute     Execute current line
  599. X    45  Leave       Edit new line, store this in hist
  600. X    46  EOF         Terminate shell
  601. X    47  NOP         Do nothing
  602. X    48  Echo^O      Echoes a ^O
  603. X    49  Beep        Echoes a ^G
  604. X
  605. X    - Other
  606. X    50  Fkey        Execute command associated to last fkey
  607. X    51  Menu        Execute command associated to last menu
  608. X    52  Undo        Undoes last edit
  609. X    53  Repeat      Repeats last function
  610. X
  611. X
  612. X    Command types
  613. X
  614. X    0   +x      Editing function x, see above descriptions
  615. X    512 +x      Setmap x,     x=0..7
  616. X    1024+x      Insert key x, x=1..255
  617. X    1536+x      Macro x       x=1..15         (*)
  618. X    2048+x      String x      x=1..15         (*)
  619. END_OF_FILE
  620. if test 11563 -ne `wc -c <'csh.doc.ad'`; then
  621.     echo shar: \"'csh.doc.ad'\" unpacked with wrong size!
  622. fi
  623. # end of 'csh.doc.ad'
  624. fi
  625. if test -f 'rawcon.c' -a "${1}" != "-c" ; then 
  626.   echo shar: Will not clobber existing file \"'rawcon.c'\"
  627. else
  628. echo shar: Extracting \"'rawcon.c'\" \(18348 characters\)
  629. sed "s/^X//" >'rawcon.c' <<'END_OF_FILE'
  630. X/*
  631. X * rawcon.c
  632. X *
  633. X * Shell 2.07M  17-Jun-87
  634. X * console handling, command line editing support for Shell
  635. X * using new console packets from 1.2.
  636. X * Written by Steve Drew. (c) 14-Oct-86.
  637. X * 16-Dec-86 Slight mods to rawgets() for Disktrashing.
  638. X *
  639. X * Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
  640. X * Version 5.00L by Urban Mueller 17-Feb-91
  641. X *
  642. X */
  643. X
  644. X#include "shell.h"
  645. X
  646. Xstatic int myget( void );
  647. Xstatic void myunget(int c);
  648. Xstatic void setrawcon( long flag, int ievent );
  649. Xstatic int get_seq( long *param );
  650. Xstatic int bkspcword( int i, int max, int cnt );
  651. X
  652. X
  653. X#if RAW_CONSOLE
  654. X
  655. Xstatic char *tyahdptr, *lasttya;
  656. Xstatic int tabctr, qcdctr, unget;
  657. X
  658. X#define SETRAW setrawcon(-1L,1);
  659. X#define SETCON setrawcon( 0L,1);
  660. X
  661. Xint w_width;
  662. Xextern char *MenuCommand[MAXMENUS][MAXITEMS];
  663. X
  664. X#define CTRL  -64
  665. X#define SHIFT 512
  666. X#define ESC   1024
  667. X
  668. X#define CUP   256
  669. X#define CDN   257
  670. X#define CRT   258
  671. X#define CLT   259
  672. X#define TAB   9
  673. X
  674. Xstatic int Curmap;
  675. Xstatic USHORT *Keymap[8];
  676. Xstatic USHORT DefKeymap0[]={
  677. X       CLT,  0, /* CursLt = Move.Left  */
  678. X       CRT,  1, /* CursRt = Move.Right */
  679. X SHIFT+CLT,  2, /* SCursLt= Move.WordL */
  680. X SHIFT+CRT,  3, /* SCursRt= Move.WordR */
  681. X   ESC+CLT,  4, /* ESC-CLt= Move.SOL   */
  682. X   ESC+CRT,  5, /* ESC-CRt= Move.EOL   */
  683. X  CTRL+'A',  4, /* ^A     = Move.SOL   */
  684. X  CTRL+'E',  5, /* ^E     = Move.EOL   */
  685. X  CTRL+'Z',  4, /* ^Z     = Move.SOL   */
  686. X         8, 10, /* BackSp = Del.BackSp */
  687. X       127, 11, /* Delete = Del.Delete */
  688. X   ESC+  8, 12, /* ESC-BkS= Del.WordL  */
  689. X   ESC+127, 13, /* ESC-Del= Del.WordR  */
  690. X  CTRL+'W', 12, /* ^W     = Del.WordL  */
  691. X  CTRL+'B', 14, /* ^B     = Del.SOL    */
  692. X  CTRL+'K', 15, /* ^K     = Del.EOL    */
  693. X   ESC+'x',513, /* ESC-x  = Setmap 1   */
  694. X   ESC+'d', 16, /* ESC-d  = Del.Line   */
  695. X  CTRL+'X', 16, /* ^X     = Del.Line   */
  696. X       CUP, 20, /* CursUp = Hist.Back  */
  697. X       CDN, 21, /* CursDn = Hist.Forw  */
  698. X   ESC+CUP, 22, /* ECursUp= Hist.Beg   */
  699. X   ESC+CDN, 23, /* ECursDn= Hist.End   */
  700. X SHIFT+CUP, 24, /* SCursUp= Hist.Compl */
  701. X   ESC+CUP, 24, /* ESC-!  = Hist.Compl */
  702. X   ESC+ 13, 25, /* ESC-Ret= Hist.Exec  */
  703. X  CTRL+'T', 26, /* ^T     = Hist.Tail  */
  704. X SHIFT+CDN, 27, /* SCursDn= Hist.Clr   */
  705. X  CTRL+'P', 28, /* ^P     = Hist.DupWrd*/
  706. X       TAB, 30, /* Tab    = Comp.Norm  */
  707. X SHIFT+TAB, 31, /* STab   = Comp.Part  */
  708. X   ESC+TAB, 32, /* ESC-TAB= Comp.All   */
  709. X   ESC+'c', 33, /* ESC-c  = Comp.CD    */
  710. X   ESC+'~', 34, /* ESC-~  = Comp.LastCD*/
  711. X   ESC+'i', 40, /* ESC-i  = Spec.Insert*/
  712. X  CTRL+'L', 43, /* ^L     = Spec.Refr  */
  713. X        10, 44, /* Enter  = Spec.Accept*/
  714. X        13, 44, /* ^Enter = Spec.Accept*/
  715. X  CTRL+'N', 45, /* ^N     = Spec.Next  */
  716. X  CTRL+'O', 48, /* ^O     = Spec.EchoO */
  717. X CTRL+'\\', 46, /* ^\     = Spec.EOF   */
  718. X       260, 42, /* Help   = Misc.Help  */
  719. X       271, 51, /* Menu   = Menu       */
  720. X  CTRL+'U', 52, /* Undo   = Spec.Undo  */
  721. X  CTRL+'R', 53, /* Repeat = Spec.Repeat*/
  722. X         0,  0
  723. X};
  724. X
  725. Xstatic USHORT DefKeymap1[]={
  726. X         8, 14,
  727. X       127, 15
  728. X};
  729. X
  730. Xstatic char *Line, *Prompt;
  731. Xstatic int Pl;
  732. Xstatic char LastDir[128];
  733. X
  734. Xvoid
  735. Xinitmap(void)
  736. X{
  737. X    if( !Keymap[0] )
  738. X        Keymap[0]=DefKeymap0, Keymap[1]=DefKeymap1;
  739. X}
  740. X
  741. Xchar *
  742. Xrawgets( char line[], char prompt[] )
  743. X{
  744. X    static int inslen, lastrecall=-1;
  745. X    static int lastfn, lastkey;
  746. X
  747. X    int    n, pl, max, i, c, key, fn, cnt;
  748. X    USHORT *p;
  749. X    char   *s, *ps, typeahd[256], undo[256], *src, tmp;
  750. X    int    savn, insert=1, recall, undo_i=0, undo_max=0;
  751. X    struct HIST *hist;
  752. X    char   **eav=NULL, *ret, fake;
  753. X    int    eac, eactr=0;
  754. X    long   param[10], *par;
  755. X
  756. X    typeahd[0]=0;
  757. X    tyahdptr=lasttya=typeahd;
  758. X
  759. X    newwidth();
  760. X
  761. X    if ( o_noraw || !IsInteractive(Input()) ) {
  762. X        if( IsInteractive(Input())) {
  763. X            printf("%s",prompt);
  764. X            fflush(stdout);
  765. X        }
  766. X        return(gets(line));
  767. X    }
  768. X
  769. X    if (WaitForChar((long)Input(), 100L) ||   /* don't switch to 1L ...*/
  770. X            CHARSWAIT(stdin)) {               /* else causes read err's*/
  771. X        gets(line);
  772. X        return(line);
  773. X    }
  774. X
  775. X    SETRAW;
  776. Xbegin:
  777. X    printf("\015%s\033[6n",prompt);
  778. X    fake= savn = pl = n = 0;
  779. X    tyahdptr = typeahd;
  780. X
  781. X    while( (typeahd[n]=getchar()) != 'R') {
  782. X        if (typeahd[n] == 155) savn = n;
  783. X        if (typeahd[n] == 27 && getchar()=='[')
  784. X            typeahd[n] =155, savn=n;
  785. X        n++;
  786. X    }
  787. X    /* typeahd now contains possible type a head chars
  788. X       followed by <CSI> cursor position report. */
  789. X
  790. X    typeahd[savn]  = '\0';
  791. X    if (typeahd[n-2] != ';') pl = (typeahd[n-2] -'0') * 10;
  792. X    pl += typeahd[n-1] - 49;
  793. X    ps = line + pl;
  794. X    line[max = i = pl] = '\0';
  795. X
  796. X    Line=line; Prompt=prompt; Pl=pl;
  797. X
  798. X    if (s = get_var (LEVEL_SET, "_insert")) insert = atoi(s) ? 1 : 0;
  799. X
  800. X    if( (recall=lastrecall)>=0 ) {
  801. X        lastrecall=-1;
  802. X        goto recallh;
  803. X    }
  804. X
  805. X    while( (c=myget()) != -1) {
  806. X        int esc=0;
  807. X        key=-1;
  808. X        if( c==27 ) {
  809. X            esc=ESC;
  810. X            if((c=myget())=='[')
  811. X                c=155,esc=0;
  812. X        }
  813. X        switch(c) {
  814. X        case 155:
  815. X            switch(c=myget()) {
  816. X            case 'A': key=256;       break; /* CursUp */
  817. X            case 'B': key=257;       break; /* CursDn */
  818. X            case 'C': key=258;       break; /* CursRt */
  819. X            case 'D': key=259;       break; /* CursLt */
  820. X            case 'T': key=256+SHIFT; break; /* SCursUp */
  821. X            case 'S': key=257+SHIFT; break; /* SCursDn */
  822. X            case ' ':
  823. X                switch( myget() ) {
  824. X                case '@': key=258+SHIFT; break; /* SCursRt */
  825. X                case 'A': key=259+SHIFT; break; /* SCursLt */
  826. X                }
  827. X                break;
  828. X            case 'Z': key= 9+SHIFT;       break; /* STab    */
  829. X            case '?': key= 260; myget();  break; /* Help    */
  830. X            default :
  831. X                myunget(c);
  832. X                par=param;
  833. X                do {
  834. X                    for( *par=0; (c=myget())>='0' && c<='9';  )
  835. X                        *par=10* *par + c-'0';
  836. X                    par++;
  837. X                } while( c==';' );
  838. X                if( c=='~' ) {
  839. X                    key=param[0]+261;
  840. X                    if( key>270 ) key+=SHIFT-10;
  841. X                }
  842. X                if( c=='|' ) key=271;
  843. X            } break;
  844. X        default: key=c; break;
  845. X        }
  846. X        key+=esc;
  847. X
  848. X        for( fn=-1, p=Keymap[Curmap]; *p; p+=2 )
  849. X            if( *p==key )
  850. X                { fn=p[1]; break; }
  851. X        if( fn==-1 && key>=261 && key<=270 || key>=261+SHIFT && key<=270+SHIFT )
  852. X            fn=50;
  853. X
  854. X        if( fn!=52 && !*lasttya) {
  855. X            memcpy( undo+pl, line+pl, max-pl );
  856. X            undo_i=i; undo_max=max;
  857. X        }
  858. X
  859. X        switch( fn/512 ) {
  860. X        case 1:
  861. X            fn&=511;
  862. X            if( fn<8 && Keymap[fn] ) Curmap=fn;
  863. X            fn=-2;
  864. X            break;
  865. X        case 2:
  866. X            key=fn&511, fn=-1;
  867. X            break;
  868. X        }
  869. X
  870. X        if( fn!=-2 )
  871. X            Curmap=0;
  872. X
  873. X        if( fn!=53 && !*lasttya )
  874. X            lastfn=fn, lastkey=key;
  875. X
  876. Xdofn:
  877. X        switch( fn ) {
  878. X        case -2:
  879. X            break;
  880. X
  881. X        case 0:                                 /* cursor left  */
  882. X            if (i > pl) 
  883. X                i--, printf("\033[D");
  884. X            break;
  885. X        case 1:                                 /* cursor right */
  886. X            if (i < max)
  887. X                i++, printf("\033[C");
  888. X            break;
  889. X        case 2:                                 /* word left    */
  890. X            for (cnt=0; i>pl && line[i-1] == ' '; cnt++,i--); 
  891. X            for (     ; i>pl && line[i-1] != ' '; cnt++,i--);
  892. X            if( cnt ) printf("\033[%dD",cnt);
  893. X            break;
  894. X        case 3:                                 /* word right   */
  895. X            for( cnt=0; i<max && line[i] != ' '; i++,cnt++) ;
  896. X            for(      ; i<max && line[i] == ' '; i++,cnt++) ;
  897. X            if( cnt ) printf("\033[%dC",cnt);
  898. X            break;
  899. X        case 4:                                 /* beg of line  */
  900. X            if (i>pl) printf("\033[%dD",i-pl);
  901. X            i = pl;
  902. X            break;
  903. X        case 5:                                 /* end of line  */
  904. X            if (i!=max) printf("\033[%dC",max - i);
  905. X            i = max;
  906. X            break;
  907. X
  908. X        case 10:                                /* backspace    */
  909. X            if (i > pl) {
  910. X                i--;
  911. X                printf("\010");
  912. X            } else break;
  913. X        case 11:                                /* delete       */
  914. X            if (i < max) {
  915. X                int j,t,l = 0;
  916. X                memmove(&line[i],&line[i+1],max-i);
  917. X                --max;
  918. X                printf("\033[P");
  919. X                j = w_width - i % w_width - 1;  /* amount to end */
  920. X                t = max/w_width - i/w_width;    /* no of lines   */
  921. X                for(n = 0; n < t; n++) {
  922. X                    l += j;                     /* # of char moved*/
  923. X                    if (j) printf("\033[%dC",j);/* goto eol       */
  924. X                    printf("%c\033[P",line[w_width*(i/w_width+n+1)-1]);
  925. X                    j = w_width-1;
  926. X                }
  927. X                if (t)
  928. X                    printf("\033[%dD",l+t);     /* get back       */
  929. X            }
  930. X            break;
  931. X        case 12:                                /* bkspc word     */
  932. X            cnt= bkspcword(i,max,-1);
  933. X            max-=cnt; i-=cnt;
  934. X            break;
  935. X        case 13:
  936. X            for( cnt=0; i<max && line[i]!=' '; i++,cnt++ ) ;
  937. X            for(      ; i<max && line[i]==' '; i++,cnt++ ) ;
  938. X            if ( cnt ) printf("\033[%dC",cnt);
  939. X            cnt=bkspcword(i,max,cnt);
  940. X            i-=cnt; max-=cnt;
  941. X            break;
  942. X        case 14:
  943. X            cnt=bkspcword(i,max,i-pl);
  944. X            i-=cnt; max-=cnt;
  945. X            break;
  946. X        case 16:                                /* delete line    */
  947. X            if (i>pl) printf("\033[%dD",i-pl);
  948. X            i = pl;
  949. X        case 15:                                /* delete to EOL  */
  950. X            printf("\033[J");
  951. X            max = i;
  952. X            line[i] = '\0';
  953. X            break;
  954. X
  955. X
  956. X        case 20:                                /* history up   */
  957. X            ++recall;
  958. X        case 21:                                /* history down */
  959. Xrecallh:
  960. X            line[pl] = '\0';
  961. X            if (recall >= 0 || fn==20) {
  962. X                if ( fn==21 ) --recall;
  963. X                n=recall;
  964. X                if (recall >= 0) {
  965. X                    for(hist = H_head; hist && n--;
  966. X                    hist = hist->next);
  967. X                    if (hist) strcpy(&line[pl],hist->line);
  968. X                    else recall = H_len;
  969. X                }
  970. X            }
  971. X            if (i != pl)
  972. X                printf("\033[%dD",i-pl);
  973. X            printf("\033[J%s",ps);
  974. X            i = max = strlen(ps) + pl;
  975. X            break;
  976. X        case 22:                                /* beg of hist */
  977. X            recall = H_len-1;
  978. X        case 23:                                /* end of hist */
  979. X            line[pl] = '\0';
  980. X            if (fn == 23) {
  981. X                recall = 0;
  982. X                if (H_head) strcpy(&line[pl], H_head->line);
  983. X            } else if (H_tail)
  984. X                strcpy(&line[pl], H_tail->line);
  985. X            printf("\015\033[J%s%s", prompt, ps);
  986. X            i = max = strlen(ps) + pl;
  987. X            break;
  988. X        case 24:                                /* complete hist */
  989. X            line[max]=0;
  990. X            if( s=get_history(&line[pl-1],0 )) {
  991. X                if (i>pl) printf("\033[%dD\033[J",i-pl);
  992. X                line[i=max=pl]=0;
  993. X                strncpy(typeahd,s,256);
  994. X                tyahdptr=typeahd;
  995. X            }
  996. X            break;
  997. X        case 25:                                /* exec hist  */
  998. X            lastrecall= recall;
  999. X            goto done;
  1000. X        case 26:                                /* tail of prev */
  1001. X            if( H_head && (s=H_head->line) && (s=index(s,' ')) )
  1002. X                tyahdptr=s;
  1003. X            break;
  1004. X        case 27:                                /* botton   */
  1005. X            recall=-1;
  1006. X            goto recallh;
  1007. X        case 28:                                /* duplicate word */
  1008. X            for(s=line+i; s>ps && *(s-1)==' '; --s ) ;
  1009. X            tmp=*s; *s=0;
  1010. X            if( !(src=rindex(ps,' '))) src="";
  1011. X            strcpy(tyahdptr=typeahd,src);
  1012. X            *s=tmp;
  1013. X            break;
  1014. X
  1015. X        case 30:                                /* complete */
  1016. X        case 31:
  1017. X        case 32:
  1018. X        case 33: {
  1019. X            static int lastcompl;
  1020. X            int j, k, n, e, cnt, len, radlen;
  1021. X            char *name, *q, abbrev;
  1022. X
  1023. X            abbrev= fn==31;
  1024. Xcomplete:
  1025. X            tyahdptr="";
  1026. X            if( tabctr!=0 ) {
  1027. X                char *dest=typeahd, *lcd;
  1028. X
  1029. X                lastcompl=fn;
  1030. X                for( cnt=0; i<max && line[i]!=' '; ++i, ++cnt ) ;
  1031. X                if(cnt) printf("\033[%dC",cnt);
  1032. X                for( e=i, j=i-1, cnt=0; j>=pl && line[j]!=' ' && line[j]!='<' &&
  1033. X                                 line[j]!='>' && line[j]!=';' ; --j ) cnt++;
  1034. X                ++j;
  1035. X
  1036. X                if( line[j]=='~' && (lcd=get_var(LEVEL_SET,v_lcd))) {
  1037. X                    strcpy(dest,lcd);
  1038. X                    dest+=strlen(dest);
  1039. X                    j++;
  1040. X                }
  1041. X                memcpy(dest,&line[j],e-j);
  1042. X                dest+=e-j;
  1043. X                if( fn!=33 )
  1044. X                    *dest++='*';
  1045. X                *dest=0;
  1046. X                if( eav ) free_expand( eav ), eav=NULL;
  1047. X                breakreset();
  1048. X                tabctr=1;
  1049. X                if( fn==33 ) {
  1050. X                    strncpy(LastDir,typeahd,128);
  1051. X                    if( !quick_cd( name=typeahd+128, LastDir, 0))
  1052. X                        { putchar(7); break; }
  1053. X                } else {
  1054. X                    eav =expand(typeahd,&eac);
  1055. X                    if( eac==0 ) { putchar(7); break; }
  1056. X                    QuickSort(eav, eac);
  1057. X                    if( fn==30 )
  1058. X                        name=eav[ eactr=0 ];
  1059. X                    else
  1060. X                        name=compile_av(eav,0,eac,' ',1), tabctr=0;
  1061. X                } 
  1062. X                inslen=cnt;
  1063. X            } else {
  1064. X                abbrev=0, tabctr=1;
  1065. X                if( lastcompl==33 ) {
  1066. X                    quick_cd( name=typeahd+128, LastDir, 1);
  1067. X                } else {
  1068. X                    if( !eac ) break;
  1069. X                    name=eav[eactr=++eactr % eac];
  1070. X                }
  1071. X            }
  1072. X            len=bkspcword(i,max,inslen);
  1073. X            i-=len; max-=len;
  1074. X            if( abbrev && eac>1) {
  1075. X                strcpy( typeahd, eav[0] );
  1076. X                radlen= 9999;
  1077. X                for( k=0; k<eac; k++ ) {
  1078. X                    if ( (n=strlen(eav[k])) < radlen ) radlen=n;
  1079. X                    for( n=0; n<radlen && eav[0][n]==eav[k][n]; n++ ) ;
  1080. X                    if ( n<radlen ) radlen=n;
  1081. X                }
  1082. X                typeahd[radlen]=0;
  1083. X                eactr--;
  1084. X            } else {
  1085. X                if( lastcompl==32 ) {
  1086. X                    strncpy( typeahd,name,250 );
  1087. X                    name[250]=0;
  1088. X                } else {
  1089. X                    strcpy(typeahd,(q=index( name, ' ' )) ? "\"" : "" );
  1090. X                    strcat(typeahd,name);
  1091. X                    if( q ) strcat(typeahd,"\"");
  1092. X                    if( lastcompl==33 || isdir(name) )
  1093. X                        appendslash( typeahd );
  1094. X                    else 
  1095. X                        strcat( typeahd, " " );
  1096. X                }
  1097. X            }
  1098. X            tyahdptr=typeahd;
  1099. X            inslen=strlen(typeahd);
  1100. X            }
  1101. X            break;
  1102. X        case 34:
  1103. X            strncpy(typeahd,get_var( LEVEL_SET, v_lcd ),230);
  1104. X            appendslash(tyahdptr=typeahd);
  1105. X            break;
  1106. X
  1107. X        case 40:                      /* ins/ovr */
  1108. X            insert ^= 1;
  1109. X            break;
  1110. X        case 41:                      /* quit */
  1111. X            strcpy(ps,"quit");
  1112. X            goto done;
  1113. X        case 42:                      /* help */
  1114. X            strcpy(ps,"help");
  1115. X            goto done;
  1116. X        case 43:                      /* refresh   */
  1117. X            if ((n = i/w_width)) printf("\033[%dF",n);
  1118. X            printf("\015\033[J%s%s",prompt,ps);
  1119. X            i = max;
  1120. X            break;
  1121. X        case 44:
  1122. X            line[max] = '\0';
  1123. Xdone:        printf("\033[%dC\n",max - i);
  1124. X            strcpy(line, ps);
  1125. X            ret=line;
  1126. X            if( fake ) goto begin;
  1127. X            goto exit;
  1128. X        case 45:                      /* leave   */
  1129. X            line[max] = '\0';
  1130. X            add_history( ps );
  1131. X            fake=1;
  1132. X            goto done;
  1133. X        case 46:                      /* EOF */
  1134. X            ret=NULL;
  1135. X            goto exit;
  1136. X        case 47:
  1137. X            break;
  1138. X        case 48:
  1139. X            printf("\017");
  1140. X            break;
  1141. X        case 49:
  1142. X            printf("\07");
  1143. X            break;
  1144. X
  1145. X        case 50: {
  1146. X            char fkeys[8];
  1147. X            sprintf(fkeys,"%c%d",param[0]>=10?'F':'f',param[0]%10+1);
  1148. X            if (s = get_var(LEVEL_SET, fkeys)) {
  1149. X                tyahdptr = strcpy(typeahd,s);
  1150. X                a0tospace( tyahdptr );
  1151. X            }
  1152. X            break;
  1153. X            }
  1154. X        case 51: {
  1155. X            int class=param[0], code=param[2];
  1156. X            if( class==10 ) {
  1157. X                int num=MENUNUM( code ), item=ITEMNUM( code );
  1158. X                tyahdptr="";
  1159. X                if( num>=0 && num<MAXMENUS && item>=0 && item<=MAXITEMS )
  1160. X                    tyahdptr=MenuCommand[num][item];                                 
  1161. X            }
  1162. X            if( class==11 ) {
  1163. X                strcpy(ps,"quit");
  1164. X                goto done;
  1165. X            }
  1166. X            }
  1167. X        case 52: {
  1168. X            int t;
  1169. X
  1170. X            if ((n = i/w_width)) printf("\033[%dF",n);
  1171. X            swapmem( undo+pl, line+pl, MAX( max, undo_max)-pl );
  1172. X            t=max; max=undo_max; undo_max=t;
  1173. X            t=i;   i  =undo_i;   undo_i  =t;
  1174. X            line[max]=0;
  1175. X            printf("\015\033[J%s%s",prompt,ps);
  1176. X            if( i<max ) printf("\033[%dD",max-i);
  1177. X            }
  1178. X            break;
  1179. X        case 53:
  1180. X            fn=lastfn; key=lastkey;
  1181. X            goto dofn;
  1182. X
  1183. X        default:
  1184. X            key&=255;
  1185. X            if (key == 9) key = 32;
  1186. X            if (key > 31 && (insert?max:i) < 256) {
  1187. X                if (i < max && insert) {
  1188. X                    int j,t,l = 0;
  1189. X                    memmove(&line[i+1], &line[i], max - i);
  1190. X                    printf("\033[@%c",key);
  1191. X                    t = max/w_width - i/w_width;
  1192. X                    j = w_width - i % w_width - 1;
  1193. X                    for(n = 0; n < t; n++) {
  1194. X                        l += j;
  1195. X                        if (j) printf("\033[%dC",j);
  1196. X                        printf("\033[@%c",line[w_width*(i/w_width+n+1)]);
  1197. X                        j = w_width-1;
  1198. X                    }
  1199. X                    if (t) printf("\033[%dD",l + t);
  1200. X                    ++max;
  1201. X                }
  1202. X                else {
  1203. X                    if(i == pl && max == i) printf("\015%s%s",prompt,ps);
  1204. X                    putchar(key);
  1205. X                }
  1206. X                line[i++] = key;
  1207. X                if (max < i) max = i;
  1208. X                line[max] = '\0';
  1209. X            }
  1210. X        }
  1211. X    }
  1212. X    ret=NULL;
  1213. Xexit:
  1214. X    newwidth();
  1215. X    if( eav ) free_expand(eav);
  1216. X    SETCON;
  1217. X    return ret;
  1218. X}
  1219. X
  1220. Xint
  1221. Xbkspcword( int i, int max, int cnt )
  1222. X{
  1223. X    int o=i;
  1224. X
  1225. X    if( !cnt ) return 0;
  1226. X
  1227. X    if( cnt==-1 ) {
  1228. X        cnt=0;
  1229. X        while( i>Pl && Line[i-1]==' ' )  i--, cnt++;
  1230. X        while( i>Pl && Line[i-1]!=' ' )  i--, cnt++;
  1231. X    } else 
  1232. X        i-=cnt;
  1233. X
  1234. X    if( cnt ) printf("\033[%dD",cnt);
  1235. X    memmove( Line+i, Line+o, max-o );
  1236. X    memset ( Line+max-cnt, ' ', cnt  );
  1237. X    
  1238. X    printf("%s",Line+i);
  1239. X    
  1240. X    if( max-i ) printf("\033[%dD", max-i );
  1241. X    fflush(stdout);
  1242. X    Line[max-=cnt]=0;
  1243. X
  1244. X    return cnt;
  1245. X}
  1246. X
  1247. Xvoid
  1248. Xsetrawcon( long flag, int ievent ) /* -1L=RAW:, 0L=CON: */
  1249. X{
  1250. X    static char menuon, button;
  1251. X    long packargs[8];
  1252. X
  1253. X    if( !o_nowindow && ievent && flag==0 && menuon)
  1254. X        printf("\033[10}"), menuon=0;
  1255. X
  1256. X    packargs[0]=flag;
  1257. X    SendPacket(994L, packargs, (void *)Myprocess->pr_ConsoleTask);
  1258. X
  1259. X    if( !o_nowindow && ievent && flag==-1 ) {
  1260. X        if( !menuon )
  1261. X            printf("\033[10{"), menuon=1;
  1262. X        if( !button )
  1263. X            printf("\033[11{"), button=1;
  1264. X    }
  1265. X    fflush(stdout);
  1266. X}
  1267. X
  1268. X
  1269. X
  1270. Xstatic int row, height, cnt, noquick=1;
  1271. Xstatic char scrollstr[10];
  1272. X
  1273. Xextern BPTR OldCin;
  1274. X
  1275. Xstatic int FromTee;
  1276. X
  1277. Xvoid
  1278. Xprepscroll( int fromtee )
  1279. X{
  1280. X    BPTR truecin=0;
  1281. X    long param[8];
  1282. X
  1283. X    row=height=0;
  1284. X    FromTee=fromtee;
  1285. X
  1286. X    if(( noquick=!o_scroll ||o_noraw || o_nofastscr ))
  1287. X        return;
  1288. X    if(( noquick=!IsInteractive(Output()) && !fromtee ))
  1289. X        return;
  1290. X    if( !IsInteractive(Input())) {
  1291. X        truecin=Myprocess->pr_CIS;
  1292. X
  1293. X        if( noquick=!IsInteractive(OldCin) )
  1294. X            return;
  1295. X
  1296. X        Myprocess->pr_CIS = DEVTAB(stdin) = OldCin;
  1297. X    }
  1298. X
  1299. X    if( !CHARSWAIT(stdin) ) {
  1300. X        SETRAW;
  1301. X        fprintf(fromtee?stderr:stdout,"\033[ q");
  1302. X        get_seq( param );
  1303. X        height=param[2];
  1304. X        while( getchar()!='r') ;
  1305. X
  1306. X        fprintf(fromtee?stderr:stdout,"\033[6n");
  1307. X        get_seq( param );
  1308. X        row=param[0];
  1309. X
  1310. X        SETCON;
  1311. X
  1312. X        cnt= height-row+1;
  1313. X        noquick= height<o_minrows;
  1314. X    }
  1315. X
  1316. X    sprintf(scrollstr,"\033[%cS\033[%cA", o_scroll+'0', o_scroll+'0');
  1317. X
  1318. X    if( truecin )
  1319. X        Myprocess->pr_CIS = DEVTAB(stdin) = truecin;
  1320. X}
  1321. X
  1322. Xstatic int
  1323. Xget_seq( long *param )
  1324. X{
  1325. X    int c;
  1326. X
  1327. X    while( (c=getchar())!=155 ) ;
  1328. X    do {
  1329. X        *param=0;
  1330. X        while( (c=getchar())>='0' && c<='9' )
  1331. X            *param=10* *param + c-'0';
  1332. X        param++;
  1333. X    } while( c==';' );
  1334. X
  1335. X    return c;
  1336. X}
  1337. X
  1338. X
  1339. Xvoid
  1340. Xquickscroll( void )
  1341. X{
  1342. X    if( noquick ) return;
  1343. X
  1344. X    if( --cnt<=0 ) {
  1345. X        cnt=o_scroll;
  1346. X        fprintf( FromTee ? stderr : stdout, "%s",scrollstr);
  1347. X    }
  1348. X}
  1349. X
  1350. Xint
  1351. Xdo_keymap( void )
  1352. X{
  1353. X    int i, n, len;
  1354. X    USHORT *tmp, *put, *get, *map;
  1355. X    char   *ind;
  1356. X
  1357. X    n=myatoi(av[1],0,7);
  1358. X    if( atoierr ) return 20;
  1359. X
  1360. X    map=Keymap[n]; len=0;
  1361. X    if( map )
  1362. X        for( len=0; map[2*len]; len++ ) ;
  1363. X
  1364. X    put=tmp=salloc((len+ac)*2*sizeof(USHORT));
  1365. X    for( i=2; i<ac; i++ ) {
  1366. X        if( !(ind=index(av[i],'='))) {
  1367. X            ierror( av[i],500);
  1368. X            free( tmp );
  1369. X            return 20;
  1370. X        }
  1371. X        *put++=atoi(av[i]);
  1372. X        *put++=atoi(ind+1);
  1373. X    }
  1374. X
  1375. X    for( i=0; i<len; i++ ) {
  1376. X        for( get=tmp; get<put; get+=2 )
  1377. X            if( *get==map[2*i] )
  1378. X                break;
  1379. X        if( get==put ) {
  1380. X            *put++=map[2*i];
  1381. X            *put++=map[2*i+1];
  1382. X        }
  1383. X    }
  1384. X
  1385. X    if( map && map!=DefKeymap0 && map!=DefKeymap1 )
  1386. X        free( map );
  1387. X    Keymap[n]=tmp;
  1388. X    Curmap=0;
  1389. X
  1390. X    return 0;
  1391. X}
  1392. X
  1393. Xstatic int
  1394. Xmyget( void )
  1395. X{
  1396. X    int c;
  1397. X
  1398. X    lasttya=tyahdptr;
  1399. X    if( unget )
  1400. X        c=unget, unget=0;
  1401. X    else if( tyahdptr && *tyahdptr)
  1402. X        c=*tyahdptr++;
  1403. X    else {
  1404. X#ifndef AZTEC_C
  1405. X        fflush(stdout);
  1406. X#endif
  1407. X        if( (c=getchar())!=155 )
  1408. X            tabctr--, qcdctr--;
  1409. X    }
  1410. X
  1411. X    return c;
  1412. X}
  1413. X
  1414. Xstatic void
  1415. Xmyunget(int c)
  1416. X{
  1417. X    unget=c;
  1418. X}
  1419. X
  1420. Xint
  1421. Xnewwidth( void )
  1422. X{
  1423. X    extern struct Window *Win;
  1424. X
  1425. X    w_width=80;
  1426. X    if( !o_nowindow && Win )
  1427. X        w_width=(Win->Width-(Win->BorderLeft+Win->BorderRight))/
  1428. X                 Win->RPort->TxWidth;
  1429. X    if( w_width<1 ) w_width=1;          /* crash after resizing was reported */
  1430. X    return w_width;
  1431. X}
  1432. X
  1433. X
  1434. X
  1435. X#else
  1436. X
  1437. Xprepscroll(){}
  1438. Xquickscroll(){}
  1439. X
  1440. X#endif
  1441. X
  1442. END_OF_FILE
  1443. if test 18348 -ne `wc -c <'rawcon.c'`; then
  1444.     echo shar: \"'rawcon.c'\" unpacked with wrong size!
  1445. fi
  1446. # end of 'rawcon.c'
  1447. fi
  1448. if test -f 'sub.c' -a "${1}" != "-c" ; then 
  1449.   echo shar: Will not clobber existing file \"'sub.c'\"
  1450. else
  1451. echo shar: Extracting \"'sub.c'\" \(21464 characters\)
  1452. sed "s/^X//" >'sub.c' <<'END_OF_FILE'
  1453. X
  1454. X/*
  1455. X * SUB.C
  1456. X *
  1457. X * (c)1986 Matthew Dillon     9 October 1986
  1458. X *
  1459. X * Version 2.07M by Steve Drew 10-Sep-87
  1460. X * Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
  1461. X * Version 5.00L by Urban Mueller 17-Feb-91
  1462. X *
  1463. X */
  1464. X
  1465. X#include "shell.h"
  1466. X#include "proto.h"
  1467. X
  1468. Xstatic void del_history( void );
  1469. Xstatic int dnext( struct DPTR *dp, char **pname, int *stat);
  1470. Xstatic char *svfile( char *s1, char *s2, FIB *fib);
  1471. Xstatic int exall( BPTR lock, char *path );
  1472. Xstatic void quicksort( char **av, int n );
  1473. X
  1474. X
  1475. X#define HM_STR 0              /* various HISTORY retrieval modes */
  1476. X#define HM_REL 1
  1477. X#define HM_ABS 2
  1478. X
  1479. Xvoid
  1480. Xseterr( int err )
  1481. X{
  1482. X    static int LastErr;
  1483. X    char buf[32], *val;
  1484. X    int  stat=0;
  1485. X
  1486. X    Lastresult=err;
  1487. X
  1488. X    if( LastErr!=err ) {
  1489. X        LastErr=err;
  1490. X        sprintf(buf, "%d", err);
  1491. X        set_var(LEVEL_SET, v_lasterr, buf);
  1492. X
  1493. X        if( val=get_var(LEVEL_SET, v_stat))
  1494. X            stat = atoi(val);
  1495. X        if (stat < Lastresult) set_var(LEVEL_SET, v_stat, buf);
  1496. X    }
  1497. X}
  1498. X
  1499. X#define ISSPACE(c) ((c)==' ' || (c)==9 || (c)==0xA0)
  1500. X
  1501. Xchar *
  1502. Xnext_word( char *str )
  1503. X{
  1504. X    while (*str && ! ISSPACE(*str)) ++str;
  1505. X    while (*str &&   ISSPACE(*str)) ++str;
  1506. X    return str;
  1507. X}
  1508. X
  1509. X/*
  1510. X * FREE(ptr)   --frees without actually freeing, so the data is still good
  1511. X *               immediately after the free.
  1512. X */
  1513. X
  1514. X
  1515. Xvoid
  1516. XFree( void *ptr )
  1517. X{
  1518. X    static char *old_ptr;
  1519. X
  1520. X    if (old_ptr) free (old_ptr);
  1521. X    old_ptr = ptr;
  1522. X}
  1523. X
  1524. X/*
  1525. X * Add new string to history (H_head, H_tail, H_len,
  1526. X *  S_histlen
  1527. X */
  1528. X
  1529. Xvoid
  1530. Xadd_history( char *str )
  1531. X{
  1532. X    struct HIST *hist;
  1533. X    char *get;
  1534. X
  1535. X    for( get=str; *get; get++ )
  1536. X        if( (*get&127)<' ')
  1537. X            *get=' ';
  1538. X
  1539. X    if (H_head != NULL && !strcmp(H_head->line, str))
  1540. X        return;
  1541. X    while (H_len > S_histlen)
  1542. X        del_history();
  1543. X    hist = (struct HIST *)salloc (sizeof(struct HIST));
  1544. X    if (H_head == NULL) {
  1545. X        H_head = H_tail = hist;
  1546. X        hist->next = NULL;
  1547. X    } else {
  1548. X        hist->next = H_head;
  1549. X        H_head->prev = hist;
  1550. X        H_head = hist;
  1551. X    }
  1552. X    hist->prev = NULL;
  1553. X    hist->line = salloc (strlen(str) + 1);
  1554. X    strcpy (hist->line, str);
  1555. X    ++H_len;
  1556. X}
  1557. X
  1558. Xstatic void
  1559. Xdel_history()
  1560. X{
  1561. X    if (H_tail) {
  1562. X        --H_len;
  1563. X        ++H_tail_base;
  1564. X        free (H_tail->line);
  1565. X        if (H_tail->prev) {
  1566. X            H_tail = H_tail->prev;
  1567. X            free (H_tail->next);
  1568. X        H_tail->next = NULL;
  1569. X        } else {
  1570. X            free (H_tail);
  1571. X            H_tail = H_head = NULL;
  1572. X        }
  1573. X    }
  1574. X}
  1575. X
  1576. Xchar *
  1577. Xget_history( char *ptr, int echo )
  1578. X{
  1579. X    struct HIST *hist;
  1580. X    int len;
  1581. X    int mode = HM_REL;
  1582. X    int num  = 1;
  1583. X    char *str=NULL;
  1584. X    char *result = NULL;
  1585. X
  1586. X    if (ptr[1] >= '0' && ptr[1] <= '9') {
  1587. X        mode = HM_ABS;
  1588. X        num  = atoi(&ptr[1]);
  1589. X        goto skip;
  1590. X    }
  1591. X    switch (ptr[1]) {
  1592. X    case '!':
  1593. X        break;
  1594. X    case '-':
  1595. X        num += atoi(&ptr[2]);
  1596. X        break;
  1597. X    default:
  1598. X        mode = HM_STR;
  1599. X        str  = ptr + 1;
  1600. X        break;
  1601. X    }
  1602. Xskip:
  1603. X    switch (mode) {
  1604. X    case HM_STR:
  1605. X        len = strlen(str);
  1606. X        for (hist = H_head; hist; hist = hist->next) {
  1607. X            if (strncmp(hist->line, str, len) == 0 && *hist->line != '!') {
  1608. X                result = hist->line;
  1609. X                break;
  1610. X            }
  1611. X        }
  1612. X        break;
  1613. X    case HM_REL:
  1614. X        for (hist = H_head; hist && num--; hist = hist->next);
  1615. X        if (hist)
  1616. X        result = hist->line;
  1617. X        break;
  1618. X    case HM_ABS:
  1619. X        len = H_tail_base;
  1620. X        for (hist = H_tail; hist && len != num; hist = hist->prev, ++len);
  1621. X        if (hist)
  1622. X        result = hist->line;
  1623. X        break;
  1624. X    }
  1625. X    if( echo )
  1626. X        fprintf(stderr, result ? "%s\n" : "History failed\n", result);
  1627. X    if( !result ) result="";
  1628. X    return result;
  1629. X}
  1630. X
  1631. Xvoid
  1632. Xreplace_head( char *str )
  1633. X{
  1634. X    if (str && strlen(str) && H_head) {
  1635. X        free (H_head->line);
  1636. X        H_head->line = salloc (strlen(str)+1);
  1637. X        strcpy (H_head->line, str);
  1638. X    }
  1639. X}
  1640. X
  1641. X
  1642. X#if 0
  1643. X#define CDLEN 20
  1644. Xstatic int   cd_len=CDLEN, cd_read, cd_write, cd_current;
  1645. Xstatic char *cd_hist[CDLEN];
  1646. X
  1647. Xadd_cdhist( char *str )
  1648. X{
  1649. X    if( !str )
  1650. X        return;
  1651. X    if( cd_hist[cd_write] )
  1652. X        free(cd_hist[cd_write]);
  1653. X    cd_hist[cd_write++]=str;
  1654. X    cd_write%=cd_len;
  1655. X    cd_current=cd_write;
  1656. X}
  1657. X
  1658. Xchar *
  1659. Xback_cdhist( void )
  1660. X{
  1661. X    if( cd_current!=cd_write ) cd_current= --cd_current % cd_len;
  1662. X    return cd_hist[cd_current];
  1663. X}
  1664. X
  1665. Xchar *
  1666. Xforw_cdhist( void )
  1667. X{
  1668. X    if( cd_current!=cd_read  ) cd_current= ++cd_current % cd_len;
  1669. X    return cd_hist[cd_current];
  1670. X}
  1671. X#endif
  1672. X
  1673. Xvoid
  1674. XpError(char *str )
  1675. X{
  1676. X    int ierr = (long)IoErr();
  1677. X    ierror(str, ierr);
  1678. X}
  1679. X
  1680. Xierror( char *str, int err )
  1681. X{
  1682. X    struct PERROR *per = Perror;
  1683. X
  1684. X    setioerror(err);
  1685. X
  1686. X    if (err) {
  1687. X        for (; per->errstr; ++per) {
  1688. X            if (per->errnum == err) {
  1689. X                fprintf (stderr, "%s%s%s\n",
  1690. X                per->errstr,
  1691. X                (str) ? ": " : "",
  1692. X                (str) ? str : "");
  1693. X                return err;
  1694. X            }
  1695. X        }
  1696. X        fprintf (stderr, "Unknown DOS error %d: %s\n", err, (str) ? str : "");
  1697. X    }
  1698. X    return err;
  1699. X}
  1700. X
  1701. Xvoid
  1702. Xsetioerror( int err )
  1703. X{
  1704. X    static int LastIoError=-1;
  1705. X    char buf[20];
  1706. X
  1707. X    IoError=err;
  1708. X    if( IoError<0 ) IoError=0;
  1709. X    if( LastIoError!=IoError) {
  1710. X        LastIoError=IoError;
  1711. X        sprintf(buf, "%d", IoError);
  1712. X        set_var(LEVEL_SET, v_ioerr, buf);
  1713. X    }
  1714. X}
  1715. X
  1716. Xchar *
  1717. Xioerror(int num)
  1718. X{
  1719. X    struct PERROR *per = Perror;
  1720. X
  1721. X    for ( ; per->errstr; ++per)
  1722. X        if (per->errnum == num)
  1723. X            return per->errstr;
  1724. X    return NULL;
  1725. X}
  1726. X
  1727. X/*
  1728. X * Disk directory routines
  1729. X *
  1730. X * dptr = dopen(name, stat)
  1731. X *    struct DPTR *dptr;
  1732. X *    char *name;
  1733. X *    int *stat;
  1734. X *
  1735. X * dnext(dptr, name, stat)
  1736. X *    struct DPTR *dptr;
  1737. X *    char **name;
  1738. X *    int  *stat;
  1739. X *
  1740. X * dclose(dptr)                  -may be called with NULL without harm
  1741. X *
  1742. X * dopen() returns a struct DPTR, or NULL if the given file does not
  1743. X * exist.  stat will be set to 1 if the file is a directory.  If the
  1744. X * name is "", then the current directory is openned.
  1745. X *
  1746. X * dnext() returns 1 until there are no more entries.  The **name and
  1747. X * *stat are set.  *stat != 0 if the file is a directory.
  1748. X *
  1749. X * dclose() closes a directory channel.
  1750. X *
  1751. X */
  1752. X
  1753. Xstruct DPTR *
  1754. Xdopen( char *name, int *stat)
  1755. X{
  1756. X    struct DPTR *dp;
  1757. X
  1758. X    IoError=0;
  1759. X    *stat = 0;
  1760. X    dp = (struct DPTR *)salloc(sizeof(struct DPTR));
  1761. X    if (*name == '\0')
  1762. X        dp->lock = DupLock(Myprocess->pr_CurrentDir);
  1763. X    else
  1764. X        dp->lock = Lock (name,ACCESS_READ);
  1765. X    if (dp->lock == NULL) {
  1766. X        IoError=IoErr();
  1767. X        free (dp);
  1768. X        return NULL;
  1769. X    }
  1770. X    dp->fib = (FIB *)SAllocMem((long)sizeof(FIB), MEMF_PUBLIC);
  1771. X    if (!Examine (dp->lock, dp->fib)) {
  1772. X        pError (name);
  1773. X        dclose (dp);
  1774. X        return NULL;
  1775. X    }
  1776. X    if (dp->fib->fib_DirEntryType >= 0) *stat = 1;
  1777. X    return dp;
  1778. X}
  1779. X
  1780. Xstatic int
  1781. Xdnext( struct DPTR *dp, char **pname, int *stat)
  1782. X{
  1783. X    if (dp == NULL) return (0);
  1784. X
  1785. X    if (ExNext (dp->lock, dp->fib)) {
  1786. X        *stat = 0;
  1787. X        if( dp->fib->fib_DirEntryType >= 0)
  1788. X            *stat= dp->fib->fib_DirEntryType!=ST_USERDIR ? 2 : 1;
  1789. X        *pname = dp->fib->fib_FileName;
  1790. X        return 1;
  1791. X    }
  1792. X    return 0;
  1793. X}
  1794. X
  1795. Xint
  1796. Xdclose( struct DPTR *dp )
  1797. X{
  1798. X    if (dp == NULL)
  1799. X        return 1;
  1800. X    if (dp->fib)
  1801. X        FreeMem (dp->fib,(long)sizeof(*dp->fib));
  1802. X    if (dp->lock)
  1803. X        UnLock (dp->lock);
  1804. X    free (dp);
  1805. X    return 1;
  1806. X}
  1807. X
  1808. X
  1809. Xint
  1810. Xisdir( char *file )
  1811. X{
  1812. X    struct DPTR *dp;
  1813. X    int stat;
  1814. X
  1815. X    stat = 0;
  1816. X    if (dp = dopen (file, &stat))
  1817. X        dclose(dp);
  1818. X    return (stat!=0);
  1819. X}
  1820. X
  1821. X
  1822. Xvoid
  1823. Xfree_expand( char **av )
  1824. X{
  1825. X    char **get = av;
  1826. X
  1827. X    if (av) {
  1828. X        while (*get)
  1829. X        free (*get++-sizeof(struct file_info));
  1830. X        free (av);
  1831. X    }
  1832. X}
  1833. X
  1834. X/*
  1835. X * EXPAND(base,pac)
  1836. X *    base           - char * (example: "df0:*.c")
  1837. X *    pac            - int  *  will be set to # of arguments.
  1838. X *
  1839. X * 22-May-87 SJD.  Heavily modified to allow recursive wild carding and
  1840. X *                 simple directory/file lookups. Returns a pointer to
  1841. X *                 an array of pointers that contains the full file spec
  1842. X *                 eg. 'df0:c/sear*' would result in : 'df0:C/Search'
  1843. X *
  1844. X *                 Now no longer necessary to Examine the files a second time
  1845. X *                 in do_dir since expand will return the full file info
  1846. X *                 appended to the file name. Set by formatfile().
  1847. X *                 eg. fullfilename'\0'rwed  NNNNNN NNNN  DD-MMM-YY HH:MM:SS
  1848. X *
  1849. X *                 Caller must call free_expand when done with the array.
  1850. X *
  1851. X * base             bname =       ename =
  1852. X * ------           -------       -------
  1853. X *  "*"               ""            "*"
  1854. X *  "!*.info"         ""            "*.info" (wild_exclude set)
  1855. X *  "su*d/*"          ""            "*"      (tail set)
  1856. X *  "file.*"          ""            "file.*"
  1857. X *  "df0:c/*"         "df0:c"       "*"
  1858. X *  ""                ""            "*"
  1859. X *  "df0:.../*"       "df0:"        "*"      (recur set)
  1860. X *  "df0:sub/.../*"   "df0:sub"     "*"      (recur set)
  1861. X *
  1862. X * ---the above base would be provided by execom.c or do_dir().
  1863. X * ---the below base would only be called from do_dir().
  1864. X *
  1865. X *  "file.c"          "file.c"      ""       if (dp == 0) fail else get file.c
  1866. X *  "df0:"            "df0:"        "*"
  1867. X *  "file/file"       "file/file"   ""       (dp == 0) so fail
  1868. X *  "df0:.../"        "df0:"        "*"      (recur set)
  1869. X *
  1870. X */
  1871. X
  1872. Xchar **
  1873. Xexpand( char *base, int *pac )
  1874. X{
  1875. X    char *ptr;
  1876. X    char **eav = (char **)salloc(sizeof(char *) * (2));
  1877. X    short eleft, eac;
  1878. X    char *name;
  1879. X    char *bname, *ename, *tail;
  1880. X    int stat, recur, scr, bl;
  1881. X    struct DPTR *dp;
  1882. X
  1883. X    IoError = *pac = recur = eleft = eac = 0;
  1884. X
  1885. X    base = strcpy(malloc(strlen(base)+1), base);
  1886. X    for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr);
  1887. X
  1888. X    if (!*ptr)   /* no wild cards */
  1889. X        --ptr;
  1890. X    else
  1891. X        for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr);
  1892. X
  1893. X    if (ptr < base) {
  1894. X        bname = strcpy (malloc(1), "");
  1895. X    } else {
  1896. X        scr = ptr[1];
  1897. X        ptr[1] = '\0';
  1898. X        if (!strcmp(ptr-3,".../")) {
  1899. X            recur = 1;
  1900. X            *(ptr-3) = '\0';
  1901. X        }
  1902. X        bname = strcpy (salloc(strlen(base)+2), base);
  1903. X        ptr[1] = scr;
  1904. X    }
  1905. X    bl = strlen(bname);
  1906. X    ename = ++ptr;
  1907. X    for (; *ptr && *ptr != '/'; ++ptr);
  1908. X    scr = *ptr;
  1909. X    *ptr = '\0';
  1910. X    if (scr) ++ptr;
  1911. X    tail = ptr;
  1912. X
  1913. X    if ((dp = dopen (bname, &stat)) == NULL || (stat == 0 && *ename)) {
  1914. X        free (bname);
  1915. X        free (base);
  1916. X        free (eav);
  1917. X        return (NULL);
  1918. X    }
  1919. X
  1920. X    if (!stat) {                /* eg. 'dir file' */
  1921. X        char *p,*s;
  1922. X        for(s = p = bname; *p; ++p) if (*p == '/' || *p == ':') s = p;
  1923. X        if (s != bname) ++s;
  1924. X        *s ='\0';
  1925. X        eav[eac++] = svfile(bname,dp->fib->fib_FileName,dp->fib);
  1926. X        goto done;
  1927. X    }
  1928. X    if (!*ename) ename = "*";    /* eg. dir df0: */
  1929. X    if (*bname && bname[bl-1] != ':' && bname[bl-1] != '/') { /* dir df0:c */
  1930. X        bname[bl] = '/';
  1931. X        bname[++bl] = '\0';
  1932. X    }
  1933. X    while ((dnext (dp, &name, &stat)) && !breakcheck()) {
  1934. X        int match = compare_ok(ename,name,0);
  1935. X        if (match && (recur || !*tail)) {
  1936. X            if (eleft < 2) {
  1937. X                char **scrav = (char **)salloc(sizeof(char *) * (eac + 10));
  1938. X                memmove (scrav, eav, (eac + 1) << 2);
  1939. X                free (eav);
  1940. X                eav = scrav;
  1941. X                eleft = 10;
  1942. X            }
  1943. X            eav[eac++] = svfile(bname,name,dp->fib);
  1944. X            --eleft;
  1945. X        }
  1946. X        if ((*tail && match) || recur) {
  1947. X            int alt_ac;
  1948. X            char *search, **alt_av, **scrav;
  1949. X            BPTR lock;
  1950. X
  1951. X            if (stat!=1)           /* expect more dirs, but this not a dir */
  1952. X                continue;
  1953. X            lock = CurrentDir (dp->lock);
  1954. X            search = salloc(strlen(ename)+strlen(name)+strlen(tail)+6);
  1955. X            strcpy (search, name);
  1956. X            strcat (search, "/");
  1957. X            if (recur) {
  1958. X                strcat(search, ".../");
  1959. X                strcat(search, ename);
  1960. X            }
  1961. X            strcat (search, tail);
  1962. X            scrav = alt_av = expand (search, &alt_ac);
  1963. X            free(search);
  1964. X            CurrentDir (lock);
  1965. X            if (scrav) {
  1966. X                while (*scrav) {
  1967. X                    int l;
  1968. X                    if (eleft < 2) {
  1969. X                        char **scrav = (char **)salloc(sizeof(char *)*(eac+10));
  1970. X                        memmove ( scrav, eav, (eac + 1) << 2);
  1971. X                        free (eav);
  1972. X                        eav = scrav;
  1973. X                        eleft = 10;
  1974. X                    }
  1975. X
  1976. X                    l = strlen(*scrav);
  1977. X                    eav[eac] = salloc(bl+l+1+sizeof(struct file_info));
  1978. X                    memcpy( eav[eac], *scrav-sizeof(struct file_info),
  1979. X                    sizeof(struct file_info));
  1980. X                    eav[eac]+=sizeof(struct file_info);
  1981. X                    strcpy( eav[eac], bname);
  1982. X                    strcat( eav[eac], *scrav);
  1983. X
  1984. X                    free (*scrav-sizeof(struct file_info));
  1985. X                    ++scrav;
  1986. X                    --eleft, ++eac;
  1987. X                }
  1988. X                free (alt_av);
  1989. X            }
  1990. X        }
  1991. X    }
  1992. Xdone:
  1993. X    dclose (dp);
  1994. X    *pac = eac;
  1995. X    eav[eac] = NULL;
  1996. X    free (bname);
  1997. X    free (base);
  1998. X    if (eac)
  1999. X        return (eav);
  2000. X    free (eav);
  2001. X    return (NULL);
  2002. X}
  2003. X
  2004. Xchar *
  2005. Xstrupr( char *s )
  2006. X{
  2007. X    char *old=s;
  2008. X    while (*s) *s=toupper(*s), s++;
  2009. X    return old;
  2010. X}
  2011. X
  2012. Xchar *
  2013. Xstrlwr( char *s )
  2014. X{
  2015. X    char *old=s;
  2016. X    while (*s) *s=tolower(*s), s++;
  2017. X    return old;
  2018. X}
  2019. X
  2020. X/*
  2021. X * Compare a wild card name with a normal name
  2022. X */
  2023. X
  2024. Xint
  2025. Xcompare_ok( char *wild, char *name, int casedep)
  2026. X{
  2027. X    int queryflag;
  2028. X    char buf[260], wildbuf[260], *lowname;
  2029. X
  2030. X    if (queryflag=(*wild=='&')) wild++;
  2031. X    if (*wild=='!') *wild='~';
  2032. X
  2033. X    if (! casedep) {
  2034. X        strupr(wild);
  2035. X        strcpy(buf,name);
  2036. X        strupr(buf);
  2037. X        lowname=buf;
  2038. X    } else
  2039. X        lowname=name;
  2040. X
  2041. X    PreParse(wild, wildbuf);
  2042. X    if ( ! PatternMatch(wildbuf,lowname)) return 0;
  2043. X
  2044. X    if (queryflag) {
  2045. X        printf("Select %s%-16s%s [y/n] ? ",o_hilite,name,o_lolite);
  2046. X        gets(buf);
  2047. X        return (toupper(*buf)=='Y');
  2048. X    }
  2049. X    return 1;
  2050. X}
  2051. X
  2052. Xstatic char *
  2053. Xsvfile( char *s1, char *s2, FIB *fib)
  2054. X{
  2055. X    int len=strlen(s1)+strlen(s2)+1;
  2056. X    char *p = salloc (len+sizeof(struct file_info));
  2057. X    struct file_info *info;
  2058. X
  2059. X    info=(struct file_info *)p;
  2060. X    p+=sizeof(struct file_info);
  2061. X    strcpy(p, s1);
  2062. X    strcat(p, s2);
  2063. X    info->flags = fib->fib_Protection;
  2064. X    if( fib->fib_DirEntryType<0 ) {
  2065. X        info->size  = fib->fib_Size;
  2066. X        info->blocks= fib->fib_NumBlocks;
  2067. X    } else {
  2068. X        info->size  = -1;
  2069. X        info->blocks= 0;
  2070. X    }
  2071. X    if( fib->fib_Comment[0] )
  2072. X        info->flags|= 1<<30;
  2073. X    info->date=fib->fib_Date;
  2074. X    info->class[0]=1;
  2075. X    return p;
  2076. X}
  2077. X
  2078. X
  2079. X
  2080. Xstatic FILE *out;
  2081. Xstatic int NumDirs;
  2082. X
  2083. Xvoid
  2084. Xexpand_all( char *name, FILE *file )
  2085. X{
  2086. X    BPTR lock;
  2087. X    char path[300];
  2088. X    FIB  *fib;
  2089. X
  2090. X    out=file;
  2091. X    printf( " %s\n", name );
  2092. X    NumDirs=0;
  2093. X
  2094. X    if(fib=AllocMem(sizeof(struct FileInfoBlock),0)) {
  2095. X        if( lock=Lock( name, ACCESS_READ )) {
  2096. X            strcpy( path, name );
  2097. X            exall( lock, path );
  2098. X            printf( "\n", NumDirs );
  2099. X        }
  2100. X        FreeMem(fib,sizeof(struct FileInfoBlock));
  2101. X    }
  2102. X}
  2103. X
  2104. Xstatic int
  2105. Xexall( BPTR lock, char *path )
  2106. X{
  2107. X    BPTR old, sublock;
  2108. X    int len;
  2109. X    struct FileInfoBlock *fib;
  2110. X
  2111. X    old=CurrentDir( lock );
  2112. X
  2113. X    if( !(fib=AllocMem(sizeof(struct FileInfoBlock),0)) )
  2114. X        return 1;
  2115. X
  2116. X    len=strlen( path );
  2117. X    Examine( lock, fib );
  2118. X    while( ExNext( lock, fib ) ) {
  2119. X        if( fib->fib_DirEntryType==ST_USERDIR )
  2120. X            if( sublock=Lock( fib->fib_FileName, ACCESS_READ )) {
  2121. X                if( !len || path[len-1]==':' )
  2122. X                    sprintf(path+len,"%s",  fib->fib_FileName);
  2123. X                else 
  2124. X                    sprintf(path+len,"/%s", fib->fib_FileName);
  2125. X                fprintf( out, "%s\n", path );
  2126. X                fprintf( stdout, " Directories: %d\015", ++NumDirs );
  2127. X                fflush ( stdout );
  2128. X                if(exall( sublock, path ))
  2129. X                    break;
  2130. X                path[len]=0;
  2131. X            }
  2132. X    }
  2133. X    FreeMem( fib, sizeof(struct FileInfoBlock));
  2134. X    CurrentDir( old );
  2135. X    return dobreak();
  2136. X}
  2137. X
  2138. X
  2139. X
  2140. X/* Sort routines */
  2141. X
  2142. Xstatic int reverse, factor;
  2143. X
  2144. Xint
  2145. Xcmp( FILEINFO *s1, FILEINFO *s2)
  2146. X{
  2147. X    return Strcmp( (char *)(s1+1), (char *)(s2+1) );
  2148. X}
  2149. X
  2150. Xint
  2151. Xsizecmp( FILEINFO *s1, FILEINFO *s2)
  2152. X{
  2153. X    return s2->size - s1->size;
  2154. X}
  2155. X
  2156. Xint
  2157. Xdatecmp( FILEINFO *s1, FILEINFO *s2 )
  2158. X{
  2159. X    int r;
  2160. X    struct DateStamp *d1=&s1->date, *d2=&s2->date;
  2161. X    if( !(r= d2->ds_Days - d1->ds_Days))
  2162. X        if( !(r=d2->ds_Minute - d1->ds_Minute ) )
  2163. X            r=d2->ds_Tick - d1->ds_Tick;
  2164. X    return r;
  2165. X}
  2166. X
  2167. X
  2168. Xint
  2169. Xnumcmp( FILEINFO *s1, FILEINFO *s2 )
  2170. X{
  2171. X    return atoi((char *)(s1+1))-atoi((char *)(s2+1));
  2172. X}
  2173. X
  2174. Xstatic void
  2175. Xenterclass( FILEINFO *info )
  2176. X{
  2177. X    char *class, *iclass=info->class, *t;
  2178. X
  2179. X    if( *iclass==1 ) {
  2180. X        if( class=getclass( (char *)(info+1))) {
  2181. X            strncpy( iclass, class, 11 );
  2182. X            iclass[11]=0;
  2183. X            if( t=index(iclass,0xA0))
  2184. X                *t=0;
  2185. X        } else 
  2186. X            iclass[0]=0;
  2187. X    }
  2188. X}
  2189. X
  2190. Xint
  2191. Xclasscmp( FILEINFO *info1, FILEINFO *info2 )
  2192. X{
  2193. X    int r;
  2194. X
  2195. X    enterclass( info1 );
  2196. X    enterclass( info2 );
  2197. X
  2198. X    r= Strcmp( info1->class, info2->class );
  2199. X    if( !r ) r=Strcmp((char *)(info1+1),(char *)(info2+1));
  2200. X    return r;
  2201. X}
  2202. X
  2203. X
  2204. Xvoid
  2205. XQuickSort( char *av[], int n)
  2206. X{
  2207. X    reverse=factor=0;
  2208. X    DirQuickSort( av, n, cmp, 0, 0 );
  2209. X}
  2210. X
  2211. Xstatic int (*compare)(FILEINFO *, FILEINFO *);
  2212. X
  2213. Xvoid
  2214. XDirQuickSort( char *av[], int n, int (*func)(FILEINFO *,FILEINFO *), int rev, int fac)
  2215. X{
  2216. X    reverse=rev; compare=func; factor=fac;
  2217. X    quicksort( av, n-1 );
  2218. X}
  2219. X
  2220. Xstatic int
  2221. Xdocompare(char *s1,char *s2)
  2222. X{
  2223. X    FILEINFO *i1=(FILEINFO *)s1-1, *i2=(FILEINFO *)s2-1;
  2224. X    int r=(*compare)( i1,i2 );
  2225. X
  2226. X    if( reverse ) r =-r;
  2227. X    if( factor )  r+= factor*((i2->size<0) - (i1->size<0));
  2228. X    return r;
  2229. X}
  2230. X
  2231. X
  2232. Xstatic void
  2233. Xquicksort( char **av, int n )
  2234. X{
  2235. X    char **i, **j, *x, *t;
  2236. X
  2237. X
  2238. X    if( n>0 ) {
  2239. X        i=av; j=av+n; x=av[ n>>1 ];
  2240. X        do {
  2241. X            while( docompare(*i,x)<0 ) i++;
  2242. X            while( docompare(x,*j)<0 ) --j;
  2243. X            if( i<=j )
  2244. X                { t=*i; *i=*j; *j=t; i++; j--; }
  2245. X        } while( i<=j );
  2246. X
  2247. X        if( j-av < av+n-i ) {
  2248. X            quicksort( av, j-av  );
  2249. X            quicksort( i , av+n-i);
  2250. X        } else {
  2251. X            quicksort( i , av+n-i);
  2252. X            quicksort( av, j-av  );
  2253. X        }
  2254. X    }
  2255. X}
  2256. X
  2257. X
  2258. Xint
  2259. Xfilesize( char *name )
  2260. X{
  2261. X    BPTR lock;
  2262. X    struct FileInfoBlock *fib;
  2263. X    int  len=0;
  2264. X
  2265. X    if( lock = Lock (name,ACCESS_READ)) {
  2266. X        if( fib=(struct FileInfoBlock *)AllocMem(sizeof(*fib),MEMF_PUBLIC)) {
  2267. X            if (Examine (lock, fib))
  2268. X                len=fib->fib_Size;
  2269. X            FreeMem( fib, sizeof(*fib));
  2270. X        }
  2271. X        UnLock(lock);
  2272. X    }
  2273. X    return len;
  2274. X}
  2275. X
  2276. X
  2277. X#ifndef MIN
  2278. X#define MIN(x,y) ((x)<(y)?(x):(y))
  2279. X#endif
  2280. X
  2281. Xchar **
  2282. Xand( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
  2283. X{
  2284. X    char **av=(char **)salloc(MIN(ac1,ac2)*sizeof(char *) ), *str;
  2285. X    int i, j, k=0;
  2286. X
  2287. X    for( i=0; i<ac1; i++ )
  2288. X        for( j=0, str=base ? BaseName(av1[i]) : av1[i]; j<ac2; j++ )
  2289. X            if( !Strcmp(str, base ? BaseName(av2[j]) : av2[j]))
  2290. X                av[k++]=av1[i];
  2291. X    *ac=k;
  2292. X    return av;
  2293. X}
  2294. X
  2295. Xchar **
  2296. Xwithout( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
  2297. X{
  2298. X    char **av=(char **)salloc(ac1*sizeof(char *) ), *str;
  2299. X    int i, j, k=0;
  2300. X
  2301. X    for( i=0; i<ac1; i++ ) {
  2302. X        for( j=0, str=base ? BaseName(av1[i]) : av1[i]; j<ac2; j++ )
  2303. X            if( !Strcmp(str, base ? BaseName(av2[j]) : av2[j] ) )
  2304. X                break;
  2305. X        if( j==ac2 )
  2306. X            av[k++]=av1[i];
  2307. X    }
  2308. X    *ac=k;
  2309. X    return av;
  2310. X}
  2311. X
  2312. Xchar **
  2313. Xor( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
  2314. X{
  2315. X    char **av=(char **)salloc((ac1+ac2)*sizeof(char *) ), *str;
  2316. X    int i, j, k=0;
  2317. X
  2318. X    for( i=0; i<ac1; i++ )
  2319. X        av[k++]=av1[i];
  2320. X
  2321. X    for( i=0; i<ac2; i++ ) {
  2322. X        for( j=0, str=base ? BaseName(av2[i]) : av2[i]; j<ac1; j++ )
  2323. X            if( !Strcmp(str, base ? BaseName(av1[j]) : av1[j] ) )
  2324. X                break;
  2325. X        if( j==ac1 )
  2326. X            av[k++]=av2[i];
  2327. X    }
  2328. X
  2329. X    *ac=k;
  2330. X    return av;
  2331. X}
  2332. X
  2333. Xvoid
  2334. Xclear_archive_bit( char *name )
  2335. X{
  2336. X    struct DPTR *dp;
  2337. X    int stat;
  2338. X
  2339. X    if(dp = dopen(name,&stat) ) {
  2340. X        SetProtection( name, dp->fib->fib_Protection&~FIBF_ARCHIVE);
  2341. X        dclose( dp );
  2342. X    }
  2343. X}
  2344. X
  2345. Xchar *
  2346. Xitoa( int i )
  2347. X{
  2348. X    static char buf[20];
  2349. X    char *pos=buf+19;
  2350. X    int count=4, flag=0;
  2351. X
  2352. X    if( i<0 )
  2353. X        flag=1, i=-i;
  2354. X
  2355. X    do {
  2356. X        if( !--count )
  2357. X            count=3, *--pos=',';
  2358. X        *--pos= i%10+'0';
  2359. X    } while( i/=10 );
  2360. X
  2361. X    if( flag )
  2362. X        *--pos='-';
  2363. X
  2364. X    return pos;
  2365. X}
  2366. X
  2367. Xchar *
  2368. Xitok( int i )
  2369. X{
  2370. X    static char buf[16], which;
  2371. X    char *exp=" KMG", *ptr= buf+(which=8-which);
  2372. X
  2373. X    do
  2374. X        i=(i+512)/1024, exp++;
  2375. X    while( i>1024 );
  2376. X    sprintf( ptr,"%d%c",i,*exp);
  2377. X
  2378. X    return ptr;
  2379. X}
  2380. X
  2381. Xchar *
  2382. Xnext_a0( char *str )
  2383. X{
  2384. X    while( *str && *str!=0xA0 && *str!='=' && *str!=',') str++;
  2385. X    return *str ? str+1 : NULL;
  2386. X}
  2387. X
  2388. Xstatic int
  2389. Xgethex( char *str, int l )
  2390. X{
  2391. X    int i, val=0, n, c;
  2392. X
  2393. X    if( *str=='.' ) return l==2 ? 256 : 0;
  2394. X
  2395. X    for( i=0; i<l || !l; i++ ) {
  2396. X        c=*str++;
  2397. X        if     ( c>='0' && c<='9' ) n=c-'0';
  2398. X        else if( c>='a' && c<='f' ) n=c-'a'+10;
  2399. X        else if( c>='A' && c<='F' ) n=c-'A'+10;
  2400. X        else break;;
  2401. X        val=16*val+n;
  2402. X    }
  2403. X    return (l && i!=l) ? -1 : val;
  2404. X}
  2405. X
  2406. Xstrwrdcmp( char *str, char *wrd )
  2407. X{
  2408. X    int ret;
  2409. X    char *ind=index(wrd,0xA0);
  2410. X
  2411. X    if( ind ) *ind=0;
  2412. X    ret=compare_ok(wrd,str,0);
  2413. X    if( ind ) *ind=0xA0;
  2414. X    return !ret;
  2415. X}
  2416. X
  2417. Xint
  2418. Xwrdlen( char *str )
  2419. X{
  2420. X    char *old=str;
  2421. X
  2422. X    while( *str && *str!=0xA0 ) str++;
  2423. X    return str-old;
  2424. X}
  2425. X
  2426. Xchar *classfile;
  2427. X
  2428. Xchar *
  2429. Xgetclass(char *file)
  2430. X{
  2431. X    CLASS *cl;
  2432. X    char *class, *str, *arg, *get, *buf;
  2433. X    int offs, byte, len, fail;
  2434. X    BPTR fh;
  2435. X
  2436. X    if( classfile ) {
  2437. X        char buf[80];
  2438. X        sprintf(buf,"source %s",classfile);
  2439. X        execute(buf);
  2440. X        classfile=0;
  2441. X    }
  2442. X
  2443. X    if( isdir(file) ) return "dir";
  2444. X
  2445. X    if( !(buf=calloc(1024,1))) return NULL;
  2446. X    if( !(fh=Open(file,MODE_OLDFILE))) return NULL;
  2447. X    len=Read( fh,buf,1023);
  2448. X    Close(fh);
  2449. X
  2450. X    for( cl=CRoot; cl; cl=cl->next ) {
  2451. X        class=cl->name;
  2452. X        if(!(str=next_a0(cl->name))) continue;
  2453. X        while( str ) {
  2454. X            if(!(arg=next_a0( str ))) goto nextclass;
  2455. X            switch( *str ) {
  2456. X            case 's':
  2457. X                if( (offs=strlen(file)-wrdlen(arg))<0 ) break;
  2458. X                if( !strwrdcmp(file+offs,arg)) goto found;
  2459. X                break;
  2460. X            case 'n':
  2461. X                if( !strwrdcmp(BaseName(file),arg) ) goto found;
  2462. X                break;
  2463. X            case 'd':
  2464. X                goto found;
  2465. X            case 'o':
  2466. X                offs=gethex(arg,0);
  2467. X                if( !(arg=index(arg,','))) goto nextclass;
  2468. X                if( offs>len-10 ) break;
  2469. X                for( get=buf+offs, ++arg; (byte=gethex(arg,2))>=0; arg+=2 )
  2470. X                    if( *get++!=byte && byte!=256 )
  2471. X                        goto nexttry;
  2472. X                goto found;
  2473. X            case 'c':
  2474. X                if( !len )
  2475. X                    goto nexttry;
  2476. X                for( get=buf, fail=0; get<buf+len; get++ )
  2477. X                    if( *get<9 || *get>13 && *get<32 || *get>127  )
  2478. X                        fail++;
  2479. X                if( fail*8>len )
  2480. X                    goto nexttry;
  2481. X                goto found;
  2482. X            case 'a':
  2483. X                goto nextclass;
  2484. X            default:
  2485. X                goto nextclass;
  2486. X            }
  2487. Xnexttry:    str=next_a0(arg);
  2488. X        }
  2489. Xnextclass: ;
  2490. X    }
  2491. X
  2492. X    free(buf);
  2493. X    return NULL;
  2494. X
  2495. Xfound:
  2496. X    free(buf);
  2497. X    return class;
  2498. X}
  2499. X
  2500. Xchar *
  2501. Xgetaction( char *class, char *action )
  2502. X{
  2503. X    CLASS *cl;
  2504. X    char *cur, *ind;
  2505. X    int len;
  2506. X
  2507. X    for( len=0; class[len] && class[len]!=0xA0; len++ ) ;
  2508. X    for( cl=CRoot; cl; cl=cl->next ) {
  2509. X        if( strncmp( cur=cl->name,class,len+1 ))
  2510. X            continue;
  2511. X        do
  2512. X            cur=index( cur,0xA0 );
  2513. X        while( cur && *++cur!='a');
  2514. X
  2515. X        if( cur && (cur=index( ++cur,0xA0 ))) {
  2516. X            do {
  2517. X                if( !(ind=index( ++cur,'=' )))
  2518. X                    return NULL;
  2519. X                len=ind-cur;
  2520. X                if( len==strlen(action) && !strncmp(action,cur,len))
  2521. X                    return ++ind;
  2522. X            } while( cur=index(cur,0xA0) );
  2523. X        }
  2524. X    }
  2525. X    return NULL;
  2526. X}
  2527. X
  2528. Xint
  2529. Xdoaction( char *file, char *action, char *args )
  2530. X{
  2531. X    char *class, *com, *c, *copy, *spc=index(file,' ');
  2532. X
  2533. X    if( !(class=getclass(file)))
  2534. X        return 10;
  2535. X    if( !(com=getaction(class,action)))
  2536. X        return 11;
  2537. X    if( c=index(com,0xA0) )
  2538. X        *c=0;
  2539. X    copy=salloc( strlen(com)+strlen(file)+strlen(args)+7 );
  2540. X    sprintf(copy,spc?"%s \"%s\" %s":"%s %s %s", com, file, args);
  2541. X    execute(copy);
  2542. X    free(copy);
  2543. X    if( c )
  2544. X        *c=0xA0;
  2545. X    return 0;
  2546. X}
  2547. X
  2548. Xvoid *
  2549. Xsalloc( int len )
  2550. X{
  2551. X    void *ret;
  2552. X
  2553. X    if( !len ) len++;
  2554. X
  2555. X    if( !(ret=malloc(len))) {
  2556. X        fprintf(stderr,"Out of memory -- exiting\n");
  2557. X        main_exit( 20 );
  2558. X    }
  2559. X    return ret;
  2560. X}
  2561. X
  2562. Xvoid *
  2563. XSAllocMem( long size, long req  )
  2564. X{
  2565. X    void *ret;
  2566. X
  2567. X    if( !(ret=AllocMem(size,req))) {
  2568. X        fprintf(stderr,"Out of memory -- exiting\n");
  2569. X        main_exit( 20 );
  2570. X    }
  2571. X    return ret;
  2572. X}
  2573. END_OF_FILE
  2574. if test 21464 -ne `wc -c <'sub.c'`; then
  2575.     echo shar: \"'sub.c'\" unpacked with wrong size!
  2576. fi
  2577. # end of 'sub.c'
  2578. fi
  2579. echo shar: End of archive 2 \(of 6\).
  2580. cp /dev/null ark2isdone
  2581. MISSING=""
  2582. for I in 1 2 3 4 5 6 ; do
  2583.     if test ! -f ark${I}isdone ; then
  2584.     MISSING="${MISSING} ${I}"
  2585.     fi
  2586. done
  2587. if test "${MISSING}" = "" ; then
  2588.     echo You have unpacked all 6 archives.
  2589.     rm -f ark[1-9]isdone
  2590. else
  2591.     echo You still need to unpack the following archives:
  2592.     echo "        " ${MISSING}
  2593. fi
  2594. ##  End of shell archive.
  2595. exit 0
  2596. -- 
  2597. Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
  2598. Mail comments to the moderator at <amiga-request@uunet.uu.net>.
  2599. Post requests for sources, and general discussion to comp.sys.amiga.misc.
  2600.